Sign in

Sign in a user with an email address or phone number, and either their password or a one-time code. Send `password` for the ordinary case, or `otp` after `POST /auth/otp` has emailed them a code — the second is how a person signs in without ever setting a password. Send one or the other, not both. Include `organization_id` when the account belongs to a particular organization: the same email address can exist as a separate account in several of them, and in the open network scope. Leave it out for an account that is not tied to an organization. You get back the wallet, an access token to use straight away, and a refresh token to keep the session going. A wrong password, a wrong code and an unknown account all give the same answer, so this cannot be used to find out who has an account. Signing in with a one-time code also confirms the address the code was sent to. No sign-in needed — this is the sign-in.

POST
/auth/login

Request Body

application/json

Who is signing in, and how.

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

curl -X POST "https://api.dual.network/auth/login" \  -H "Content-Type: application/json" \  -d '{    "email": "alex@example.com",    "password": "correct horse battery staple"  }'
{
  "wallet": {
    "id": "665f1c2d4b1a2c3d4e5f6a01",
    "fqdn": "dual.network",
    "email": "alex@example.com",
    "nickname": "alexf",
    "language": "en",
    "activated": true,
    "disabled": false,
    "account": {
      "address": "0x1234567890abcdef1234567890abcdef12345678",
      "type": "SMART_WALLET",
      "controller": {
        "address": "0x9876543210fedcba9876543210fedcba98765432",
        "type": "SECP256K1",
        "custody": "self-custodial"
      },
      "smart_account": {
        "chain_id": 42161,
        "factory": "0x7777777777777777777777777777777777777777",
        "implementation": "0x8888888888888888888888888888888888888888",
        "index": 0,
        "validator": "0x9999999999999999999999999999999999999999",
        "validator_type": "ECDSA",
        "version": "0.3.1"
      }
    },
    "when_created": "2026-02-01T09:00:00Z",
    "when_modified": "2026-02-01T09:00:00Z"
  },
  "access_token": "<access token>",
  "refresh_token": "<refresh token>"
}
{
  "code": 3,
  "message": "Key: 'limit' Error:Field validation for 'limit' failed on the 'lte' tag"
}
{
  "code": 3,
  "message": "limit must be 25 or less",
  "details": {}
}
{
  "code": 13,
  "message": "internal error"
}