Aplyid
An Elixir client library for the APLYiD Developer API.
Installation
Add aplyid to your list of dependencies in mix.exs:
def deps do
[
{:aplyid, "~> 0.1.0"}
]
endConfiguration
Configure environments in your config/runtime.exs:
config :aplyid,
environments: [
uat: [
base_url: "https://integration.aplyid.com",
api_key: System.get_env("APLYID_UAT_API_KEY"),
api_secret: System.get_env("APLYID_UAT_API_SECRET")
],
production: [
base_url: "https://app.aplyid.com",
api_key: System.get_env("APLYID_API_KEY"),
api_secret: System.get_env("APLYID_API_SECRET")
]
]Usage
Creating a Client
# Create a client for an environment
client = Aplyid.Client.new(environment: :uat)
# Shorthand for UAT
client = Aplyid.Client.uat()Identity Verification
# Create a verification (sends SMS to user)
{:ok, result} = Aplyid.Client.Verifications.create(client, %{
"reference" => "order-123",
"email" => "user@example.com",
"contact_phone" => "61400000000",
"firstname" => "John",
"lastname" => "Smith",
"flow_type" => "SIMPLE2"
})
# result contains:
# %{"transaction_id" => "eUmE4voe-L_BRzjG"}
# When no contact_phone is provided, the response includes a URL for manual verification:
# %{"transaction_id" => "...", "start_process_url" => "https://..."}# Resend SMS notification
{:ok, result} = Aplyid.Client.Verifications.resend_sms(client, "transaction_id")
# Resend to a different phone number
{:ok, result} = Aplyid.Client.Verifications.resend_sms(client, "transaction_id", %{
"contact_phone" => "61400111222"
})Webhook Notifications
Mount the webhook plug in your Phoenix router to receive verification events:
# lib/my_app_web/router.ex
forward "/webhooks/aplyid/uat", Aplyid.Webhook.Plug,
environment: :uat,
handler: MyApp.AplyidWebhookHandler
Implement the handler with use Aplyid.Webhook.Handler:
defmodule MyApp.AplyidWebhookHandler do
use Aplyid.Webhook.Handler
@impl true
def handle_event("completed", payload, _context) do
# Verification completed - payload contains results
:ok
end
def handle_event(_event_type, _payload, _context), do: :ok
end
Event types: "created", "completed", "updated", "archived", "error", "pending", "test".
Webhook Authentication
Authorization is verified automatically before handle_event/3 is called. Configure webhook_auth in your environment config to match the token APLYiD sends:
config :aplyid,
environments: [
uat: [
base_url: "https://integration.aplyid.com",
api_key: System.get_env("APLYID_UAT_API_KEY"),
api_secret: System.get_env("APLYID_UAT_API_SECRET"),
webhook_auth: System.get_env("APLYID_UAT_WEBHOOK_AUTH")
]
]
If webhook_auth is not configured, all requests are allowed. If configured, the plug compares the incoming Authorization header and returns 401 on mismatch.
To use custom auth logic, override verify_authorization/1 in your handler:
defmodule MyApp.AplyidWebhookHandler do
use Aplyid.Webhook.Handler
@impl true
def verify_authorization(%{authorization: auth}) do
if MyApp.Auth.valid_webhook_token?(auth), do: :ok, else: {:error, :unauthorized}
end
@impl true
def handle_event("completed", payload, _context) do
# ...
:ok
end
endError Handling
All API calls return {:ok, data} or {:error, error}:
case Aplyid.Client.Verifications.create(client, params) do
{:ok, result} ->
result["transaction_id"]
{:error, %Aplyid.Client.Error{type: :unauthorized}} ->
# Invalid API credentials
{:error, %Aplyid.Client.Error{type: :validation_error} = error} ->
# Validation failed - check error.details
{:error, error} ->
Aplyid.Client.Error.message(error)
endMock 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
- Walk through a mock verification UI flow
Setting Up the Mock Server
1. Add Optional Dependencies
The mock server requires Plug and optionally Ecto for persistence:
def deps do
[
{:aplyid, "~> 0.1.0"},
{:plug, "~> 1.14"},
{:ecto_sql, "~> 3.10"},
{:postgrex, "~> 0.17"}
]
end2. Configure the Mock Server
# config/dev.exs or config/test.exs
config :aplyid, :mock_server,
enabled: true,
embedded: true,
base_url: "http://localhost:4000/aplyid-mock",
repo: MyApp.RepoConfiguration options:
| Option | Description | Default |
|---|---|---|
enabled | Enable the mock server | false |
embedded | Skip starting Bandit (use Phoenix instead) | false |
base_url | Base URL for verification links | "http://localhost:4000" |
repo | Ecto repo for PostgreSQL persistence | Required |
webhook_url | URL to send webhook notifications to | nil |
webhook_auth | Authorization header value for webhooks | nil |
3. Create the Database Migration
mix ecto.gen.migration add_aplyid_mock_server# priv/repo/migrations/YYYYMMDDHHMMSS_add_aplyid_mock_server.exs
defmodule MyApp.Repo.Migrations.AddAplyidMockServer do
use Ecto.Migration
def up, do: Aplyid.MockServer.Migrations.up(version: 1)
def down, do: Aplyid.MockServer.Migrations.down(version: 1)
endmix ecto.migrate4. Mount in Your Phoenix Router
# lib/my_app_web/router.ex
forward "/aplyid-mock", Aplyid.MockServer.Router5. Point Your Client at the Mock Server
config :aplyid,
environments: [
uat: [
base_url: "http://localhost:4000/aplyid-mock",
api_key: "any_key",
api_secret: "any_secret"
]
]Verification Flow UI
When you create a transaction without a contact_phone, the response includes a start_process_url pointing to the mock verification flow. Open this URL in a browser to walk through the 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 mock verification data and triggers any configured webhooks.
The verification URL is generated based on the base_url config. When mounted in Phoenix at /aplyid-mock, the URL will be http://localhost:4000/aplyid-mock/l/:id. The router uses conn.script_name to correctly handle path prefixes for all internal links and redirects.
Programmatic Completion
For automated testing, skip the UI and complete transactions programmatically:
# Via helper function
Aplyid.MockServer.complete_transaction(transaction_id)
# Via HTTP endpoint
POST /mock/simulate/complete/:transaction_idMock Server API Endpoints
| Endpoint | Description |
|---|---|
POST /api/v2/send_text | Create verification transaction |
PUT /api/v2/resend_text/:id | Resend SMS notification |
GET /l/:id | Start verification flow (HTML) |
POST /mock/simulate/complete/:id | Simulate completion |
GET /health | Health check |
Test Setup
# config/test.exs
config :aplyid, :mock_server,
enabled: true,
embedded: true,
repo: MyApp.Repo,
base_url: "http://localhost:4000"
config :aplyid,
environments: [
uat: [
base_url: "http://localhost:4000",
api_key: "test_key",
api_secret: "test_secret"
]
]# In your test setup
setup do
Aplyid.MockServer.clear_all()
:ok
endLicense
MIT