# 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`:
```elixir
def deps do
[
{:idverse, "~> 0.1.0"}
]
end
```
## Configuration
Configure environments in your `config/runtime.exs`:
```elixir
# Optional mock server for development
config :idverse, :mock_server,
enabled: true,
port: 4500,
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:4500/v1",
oauth2_url: "http://localhost:4500",
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
```elixir
# Create a client for an environment
client = Idverse.Client.new(environment: :prod)
```
### Transaction Operations
```elixir
# 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:
```elixir
{: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: "https://example.com/webhook",
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:
```elixir
# config/dev.exs
config :idverse, :mock_server,
enabled: true,
port: 4500
# config/test.exs
config :idverse, :mock_server,
enabled: true,
port: 4501
```
### Using the Mock Server
Configure your client to use the mock server URLs:
```elixir
# Configure a dev environment pointing to the mock server
config :idverse,
environments: [
mock: [
base_url: "http://localhost:4500/v1",
oauth2_url: "http://localhost:4500",
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:
1. **Privacy Consent** - User confirms they accept the privacy terms
2. **Capture Photo ID** - Simulates capturing an ID document
3. **Reviewing ID Data** - Brief loading screen
4. **Check ID Details** - Displays mock extracted data for confirmation
5. **Face Verification** - Simulates the liveness check
6. **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:
```elixir
# Via helper function
Idverse.MockServer.complete_transaction(transaction_id)
# Via HTTP endpoint
POST http://localhost:4500/mock/simulate/complete/:transaction_id
```
Completed 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
```elixir
# Clear all mock state between tests
Idverse.MockServer.clear_all()
# Get configured URLs
Idverse.MockServer.base_url() # => "http://localhost:4500/v1"
Idverse.MockServer.oauth2_url() # => "http://localhost:4500"
```
### 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
1. **Add the optional dependencies** to your `mix.exs`:
```elixir
def deps do
[
{:idverse, "~> 0.1.0"},
{:ecto_sql, "~> 3.10"},
{:postgrex, "~> 0.17"}
]
end
```
2. **Configure the mock server** with your Ecto repo:
```elixir
# config/dev.exs
config :idverse, :mock_server,
enabled: true,
port: 4500,
repo: MyApp.Repo
```
3. **Create a migration** in your application:
```bash
mix ecto.gen.migration add_idverse_mock_server
```
4. **Call the library's migration functions**:
```elixir
# 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
```
5. **Run the migration**:
```bash
mix ecto.migrate
```
#### Database Tables
The migration creates two tables:
- `idverse_mock_transactions` - Stores transaction records with all verification data
- `idverse_mock_tokens` - Stores OAuth tokens
#### Schema Prefix (Multi-tenant)
For multi-tenant setups, you can specify a database schema prefix:
```elixir
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 `repo` configured, the mock server uses ETS storage (default behavior)
- With a `repo` configured, transactions persist to PostgreSQL
- All API endpoints work identically regardless of storage backend
## License
MIT