ReconbankerReconbanker
Guides

Automate OTP submission

Build a service that receives an OTP request and submits the code without a human in the dashboard.

Automate OTP submission

Banks that enforce two-factor login normally need a person to type the one-time code. If your code arrives somewhere a machine can read it — an SMS gateway, an email inbox, an authenticator service — you can close that loop automatically. This guide builds a service that learns when a code is needed and submits it through the External API.

For the concepts behind this flow, see Assisted login and OTP.

Before you start

You will need:

  • An account set to login_mode: assisted. See Sessions.
  • A way to obtain the code programmatically (for example, a webhook from your SMS provider).
  • A Reconbanker login, so you can create an API key.

Step 1: Create an API key

Create a key with the scopes your service needs. Use otp:write to submit codes and status:read if you intend to poll for status.

POST /me/api-keys
Content-Type: application/json
Authorization: Bearer <jwt>
{
  "name": "SMS relay",
  "scopes": ["otp:write", "status:read"],
  "account_ids": ["7e9a2b3c-4d5e-4f6a-9b8c-1d2e3f4a5b6c"]
}

Store the returned key somewhere safe — it is shown only once. Set account_ids to the accounts this service may act on, or leave it null for all of them. See API keys for the full reference.

Step 2: Learn when a code is needed

Pick one of two patterns.

Option A — Push (notification webhook)

Subscribe the account to the assistance_required event so Reconbanker calls you the instant a code is requested. On the account's settings, set the notification endpoint and events (see Notification settings):

{
  "notification_endpoint_url": "https://your-service.example/reconbanker/notify",
  "notification_auth_type": "bearer",
  "notification_auth_token": "<your-token>",
  "notification_events": ["assistance_required"]
}

Your endpoint then receives:

{
  "account_id": "b9c224b3-3c2b-42bd-b23e-337ae0185690",
  "type": "assistance_required",
  "status": "assistance.requested",
  "data": { "descriptor": { "length": 6, "type": "numeric" } },
  "occurred_at": "2026-06-13T03:00:00.000Z"
}

Option B — Poll (status endpoint)

If you would rather not expose an endpoint, poll the account status and act when pending_assistance appears:

GET /v1/accounts/:accountId/status
Authorization: Api-Key rbk_abcd1234_secret...
{
  "account_id": "b9c224b3-3c2b-42bd-b23e-337ae0185690",
  "session_running": true,
  "pending_assistance": {
    "id": "req-1",
    "type": "otp",
    "descriptor": { "length": 6, "type": "numeric", "purpose": "login" },
    "attempts": 0
  }
}

Step 3: Submit the code

Once your service has the code, submit it:

POST /v1/accounts/:accountId/otp
Content-Type: application/json
Authorization: Api-Key rbk_abcd1234_secret...
{ "code": "123456" }

A 202 Accepted ({ "submitted": true }) means Reconbanker took the code and forwarded it to the waiting login. It does not yet mean the bank accepted it. This endpoint is rate-limited, so submit once per code rather than retrying in a tight loop.

Testing locally

Run a tiny listener to see the notification webhook payload (Option A):

node -e "require('http').createServer((req,res)=>{let b='';req.on('data',c=>b+=c);req.on('end',()=>{console.log(req.method,req.url,b);res.end('ok')})}).listen(4000)"

Point notification_endpoint_url at it (use a tunnel such as ngrok if Reconbanker runs elsewhere), then trigger an assisted login. You can exercise the /v1 endpoints directly with curl:

curl -sX POST https://reconbanker.your-domain.com/v1/accounts/$ACCOUNT_ID/otp \
  -H "Authorization: Api-Key $RBK_KEY" \
  -H "Content-Type: application/json" \
  -d '{"code":"123456"}'

What happens next

Reconbanker forwards the code and the login continues. To confirm success, watch the account status: when the code is accepted, pending_assistance clears back to null. A rejection surfaces as a login_failed event, which you can receive through the notification webhook. (The dashboard realtime stream additionally emits an assistance.fulfilled event, but that one is not delivered to the notification webhook.) If a login keeps failing, the account can be blocked until you intervene.