Idverse
An Elixir client library for the IDVerse / IDKit identity verification API.
⚠️ AI Generated! ⚠️
Full disclosure, this repo was largely generated by Claude Code. Use at your own risk.
Installation
Add idverse to your list of dependencies in mix.exs:
def deps do
[
{:idverse, "~> 0.3.0"}
]
endConfiguration
Configure environments in your config/runtime.exs:
# Optional mock server for development
config :idverse, :mock_server,
enabled: true,
embedded: true,
base_url: "http://localhost:4000/idverse-mock",
repo: Ubre.Repo
config :idverse,
environments: [
prod: [
base_url: System.get_env("IDVERSE_BASE_URL"),
oauth2_url: System.get_env("IDVERSE_OAUTH2_URL"),
api_key: System.get_env("IDVERSE_API_KEY")
],
mock: [
base_url: "http://localhost:4000/idverse-mock/v1",
oauth2_url: "http://localhost:4000/idverse-mock",
api_key: "mock_api_key"
]
]
Each environment gets its own supervised TokenManager process that handles OAuth2 token acquisition and automatic refresh.
Usage
Creating a Client
# Create a client for an environment
client = Idverse.Client.new(environment: :prod)Transaction Operations
# Create a new verification transaction
{:ok, transaction} = Idverse.Client.Transactions.create(client, %{
name: "John Doe",
reference: "order-123",
flow_type: "NORMAL2",
phone_region_code: "61",
phone_number: "400000000",
redirect_url_success: "https://example.com/success",
redirect_url_exit: "https://example.com/exit"
})
# Get transaction details
{:ok, details} = Idverse.Client.Transactions.get(client, transaction["transaction_id"])
# Get PDF report
{:ok, pdf_binary} = Idverse.Client.Transactions.get(client, transaction_id, "pdf")
# Resend SMS notification
{:ok, response} = Idverse.Client.Transactions.resend(client, transaction_id)
# Cancel a transaction
{:ok, response} = Idverse.Client.Transactions.cancel(client, transaction_id)
# Redact transaction data
{:ok, response} = Idverse.Client.Transactions.redact(client, transaction_id, ["records", "assets", "face", "data"])Webhook Notifications
You can configure webhook notifications when creating a transaction:
{:ok, transaction} = Idverse.Client.Transactions.create(client, %{
name: "John Doe",
flow_type: "NORMAL2",
phone_region_code: "61",
phone_number: "400000000",
notifications: %{
complete: [
%{
type: "https",
url: "http://localhost:4000/webhook/idverse",
auth_header_name: "Authorization",
auth_header_value: "Bearer token123"
}
]
}
})Architecture
The library uses a supervised TokenManager GenServer for each configured environment. This provides:
- Automatic OAuth2 token acquisition using client credentials flow
- Token caching and automatic refresh before expiry
- Thread-safe token access across multiple processes
Mock Server
The library includes a built-in mock server for local development and testing. This allows you to:
- Develop without API credentials
- Run integration tests without hitting the real API
- Avoid per-transaction billing during development
Enabling the Mock Server
Add to your config files:
# config/config.exs
config :idverse, :mock_server,
enabled: true,
embedded: true,
base_url: "http://localhost:4000/idverse-mock"Using the Mock Server
Configure your client to use the mock server URLs:
# Configure a dev environment pointing to the mock server
config :idverse,
environments: [
mock: [
base_url: "http://localhost:4000/idverse-mock/v1",
oauth2_url: "http://localhost:4000/idverse-mock",
api_key: "any_key_works"
]
]
# Then create a client
client = Idverse.Client.new(environment: :mock)Verification Flow UI
When you create a transaction, the returned url points to a mock verification flow. Open this URL in a browser to walk through the verification screens:
- Privacy Consent - User confirms they accept the privacy terms
- Capture Photo ID - Simulates capturing an ID document
- Reviewing ID Data - Brief loading screen
- Check ID Details - Displays mock extracted data for confirmation
- Face Verification - Simulates the liveness check
- Verification Complete - Success screen
Completing this flow automatically marks the transaction as "completed" with realistic verification data.
Programmatic Completion
For automated testing, you can skip the UI and complete transactions programmatically:
# Via helper function
Idverse.MockServer.complete_transaction(transaction_id)
# Via HTTP endpoint
POST http://localhost:4000/mock/simulate/complete/:transaction_idCompleted transactions include realistic mock verification data (documents, liveness checks, facematch scores, etc.).
Mock Server API Endpoints
The mock server implements all IDVerse API endpoints:
| Endpoint | Description |
|---|---|
POST /oauth2/token | OAuth2 token endpoint |
POST /v1/transactions | Create transaction |
GET /v1/transactions/:id/json | Get transaction JSON |
GET /v1/transactions/:id/pdf | Get transaction PDF |
POST /v1/transactions/resend | Resend SMS |
POST /v1/transactions/cancel | Cancel transaction |
POST /v1/transactions/redact | Redact transaction data |
GET /verify/:id | Start verification flow (HTML) |
POST /mock/simulate/complete/:id | Simulate completion |
GET /health | Health check |
Test Helpers
# Clear all mock state between tests
Idverse.MockServer.clear_all()
# Get configured URLs
Idverse.MockServer.base_url() # => "http://localhost:4000/v1"
Idverse.MockServer.oauth2_url() # => "http://localhost:4000"PostgreSQL Persistence (Optional)
By default, the mock server stores transactions in ETS (in-memory), meaning data is lost when the application restarts. For development scenarios where you need persistent transactions, you can configure the mock server to use your application's PostgreSQL database.
Setup
- Add the optional dependencies to your
mix.exs:
def deps do
[
{:idverse, "~> 0.3.0"},
{:ecto_sql, "~> 3.10"},
{:postgrex, "~> 0.17"}
]
end- Configure the mock server with your Ecto repo:
# config/dev.exs
config :idverse, :mock_server,
enabled: true,
embedded: true,
base_url: "http://localhost:4000/idverse-mock",
repo: MyApp.Repo- Create a migration in your application:
mix ecto.gen.migration add_idverse_mock_server- Call the library's migration functions:
# priv/repo/migrations/YYYYMMDDHHMMSS_add_idverse_mock_server.exs
defmodule MyApp.Repo.Migrations.AddIdverseMockServer do
use Ecto.Migration
def up, do: Idverse.MockServer.Migrations.up(version: 1)
def down, do: Idverse.MockServer.Migrations.down(version: 1)
end- Run the migration:
mix ecto.migrateDatabase Tables
The migration creates two tables:
idverse_mock_transactions- Stores transaction records with all verification dataidverse_mock_tokens- Stores OAuth tokens
Schema Prefix (Multi-tenant)
For multi-tenant setups, you can specify a database schema prefix:
def up, do: Idverse.MockServer.Migrations.up(version: 1, prefix: "tenant_schema")
def down, do: Idverse.MockServer.Migrations.down(version: 1, prefix: "tenant_schema")Backward Compatibility
-
Without a
repoconfigured, the mock server uses ETS storage (default behavior) -
With a
repoconfigured, transactions persist to PostgreSQL - All API endpoints work identically regardless of storage backend
Phoenix Integration (Embedded Mode)
When deploying to production, your application typically serves traffic on a single port. The mock server's verification pages (/verify/*) need to be accessible to end users, which is a problem if the mock server runs on a separate port.
Embedded mode solves this by skipping the mock server's built-in HTTP server (Bandit) and letting you mount the router directly in your Phoenix application.
Setup
- Enable embedded mode in your config:
# config/dev.exs or config/runtime.exs
config :idverse, :mock_server,
enabled: true,
embedded: true, # Skip starting Bandit
base_url: "http://localhost:4000/idverse-mock", # For verification URLs
repo: MyApp.Repo- Forward routes in your Phoenix router:
# lib/my_app_web/router.ex
defmodule MyAppWeb.Router do
use MyAppWeb, :router
# Mount the entire mock server router
forward "/idverse-mock", Idverse.MockServer.Router
# ... your other routes
end- Update your client configuration to use Phoenix URLs:
config :idverse,
environments: [
mock: [
base_url: "http://localhost:4000/idverse-mock/v1",
oauth2_url: "http://localhost:4000/idverse-mock",
api_key: "any_key_works"
]
]Route Mounting Options
You can mount the mock server at any path:
# Mount at root (mock server handles /verify/*, /v1/*, /oauth2/*)
forward "/", Idverse.MockServer.Router
# Mount under a prefix
forward "/idverse-mock", Idverse.MockServer.Router
# Mount in a specific pipeline
scope "/", MyAppWeb do
pipe_through [:browser]
forward "/idverse-mock", Idverse.MockServer.Router
endProduction Considerations
When using embedded mode in production:
-
Set
base_urlto your production domain (e.g.,https://myapp.com/idverse-mock) - This URL is used to generate verification links sent to users via SMS
-
Configure your client's
base_urlandoauth2_urlto match your production domain - The mock server routes are served by your Phoenix application's endpoint
# config/runtime.exs
config :idverse, :mock_server,
enabled: true,
embedded: true,
base_url: System.get_env("APP_URL") <> "/idverse-mock",
repo: MyApp.RepoLicense
MIT