Skip to content
Seismic Orchestration

POST /customers/:id/accounts/crypto/external

Register a wallet the customer already controls. Synchronous: caller supplies the on-chain address, so the Account materializes at request time and is returned on account.

Shared semantics (idempotency header, response envelope, error codes) live on the create-account index.

Uniqueness

A wallet registers once per customer per currency and network. Registering the same address + currency + rail again while the account is live returns a 400 naming it — addresses compare case-insensitively, so checksum casing makes no difference. The same wallet on a different network, or holding a different currency, is a distinct account.

Registering one you deleted restores it: the original id comes back and an account.created webhook is emitted. See getting a deleted account back.

Request body

FieldTypeRequiredNotes
addressstringyesOn-chain wallet address. Validated against the chosen shape: EVM is ^0x[0-9a-fA-F]{40}$, and must look like a real wallet — placeholder, burn and patterned addresses are refused. Solana addresses must decode to a nonzero 32-byte Base58 public key; casing is significant.
shapeCryptoShapenoInferred from rail when omitted ("evm" or "sol"). If supplied, must match the rail.
railstring | numberyesCurrency-or-rail reference. By name ("ethereum", "base", …) or numeric id. Must be a supported EVM or Solana rail.
currencystring | numberyesCurrency the wallet holds ("USDC", "USDT", …). Must be settleable on the chosen rail (per currency_rails).
account_holderAccountHolderInputnoLegal owner of the wallet. Omit it and Seismic derives the holder from the customer's own KYB/KYC profile. Supply it to register a wallet owned by a third party. Its industry may be any code GET /v0/industries lists.

Headers

HeaderValue
Idempotency-KeyOptional, up to 256 characters. Re-POSTing the same (org, key) returns the existing creation request unchanged.

Response 200

{
  "request": {
    "id": "req_…",
    "customer_id": "2f10…",
    "kind": "crypto",
    "shape": "evm",
    "origin": "external",
    "currency": "USDC",
    "rails": ["ethereum"],
    "status": "completed",
    "idempotency_key": "abc-123",
    "account_id": "acct_…",
    "details": {
      "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f8b840"
    },
    "created_at": "2026-05-20T19:45:00Z",
    "updated_at": "2026-05-20T19:45:00Z"
  },
  "account": {
    "id": "acct_…",
    "customer_id": "2f10…",
    "kind": "crypto",
    "shape": "evm",
    "origin": "external",
    "currency": "USDC",
    "rails": ["ethereum"],
    "status": "active",
    "created_at": "2026-05-20T19:45:00Z",
    "updated_at": "2026-05-20T19:45:00Z",
    "details": {
      "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f8b840"
    }
  }
}

Errors

  • 400 InvalidAccountFields address: not a valid EVM address, or not a usable wallet: a placeholder or burn address (0x0000…0000, 0x000…dEaD, 0x000…deadbeef), a single repeated digit (0x1111…1111), or a repeating pattern (0x1234567890 repeated). Real addresses, including vanity ones with long runs of leading zeros, are unaffected.
  • 400 InvalidAccountFields address: not a valid 32-byte Base58 Solana public key, or the all-zero system address.
  • 400 InvalidAccountFields shape: does not match the selected rail.
  • 400 InvalidAccountFields rail: rail isn't supported, isn't settleable for the chosen currency, or doesn't match the requested shape.
  • 400 InvalidAccountFields currency: currency isn't a stablecoin / crypto kind.
  • 400 InvalidRequest account_holder.address.postal_code: the postal code doesn't match the format used by its country. Raised for a postal code taken from the customer's profile too, when account_holder is omitted.
  • 404: unknown currency or rail.

Example

The customer owns the wallet — account_holder is omitted and derived from their KYB/KYC profile:

curl -X POST "$SEISMIC_ORCHESTRATION_URL/v0/customers/2f10…/accounts/crypto/external" \
  -H "Api-Key: $SEISMIC_ORCHESTRATION_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "content-type: application/json" \
  -d '{
    "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f8b840",
    "rail": "ethereum",
    "currency": "USDC"
  }'

To register a wallet owned by a third party, pass account_holder explicitly:

curl -X POST "$SEISMIC_ORCHESTRATION_URL/v0/customers/2f10…/accounts/crypto/external" \
  -H "Api-Key: $SEISMIC_ORCHESTRATION_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "content-type: application/json" \
  -d '{
    "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f8b840",
    "rail": "ethereum",
    "currency": "USDC",
    "account_holder": {
      "type": "individual",
      "first_name": "Alice",
      "last_name": "Walker",
      "address": {
        "country": "US"
      },
      "is_third_party": true
    }
  }'

Example: external Solana wallet

Omit shape to infer sol from the rail. The returned account preserves the address exactly, including its case.

{
  "currency": "USDC",
  "rail": "solana",
  "address": "7YttLkHDoNj9wyDur5A7eD3k1ySG5NCjc1QpNSUGpEGj"
}