Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.seismic-cards.systems/llms.txt

Use this file to discover all available pages before exploring further.

Issuing a card through the Seismic API takes three phases. The first time you onboard a user you work through all three phases. Every subsequent card for that same user is a single API call — Phase C only. This guide walks you through the complete flow.
Before you start, make sure you have a valid accessToken (see Authentication), your parentAccountId, your defaultBinId, and the user’s legal name, email, phone number, date of birth, and full address. Your webhook endpoint should also be registered in the Seismic dashboard.

Phases at a glance

PhaseStepsFrequency
A. User onboardingCreate sub-account → KYC → InitializeOnce per user
B. Resource provisioningCreate cardholder → Create and fund budgetOnce per user
C. Card issuanceIssue the cardEvery card

Phase A — User onboarding

1

Create a sub-account

Every end user gets their own Seismic sub-account. The sub-account is the legal envelope that owns the user’s cardholder, budget, and cards.
POST /v1/accounts/register
Host: sandbox-api.seismic.systems
x-access-token: <your access token>
Content-Type: application/json

{
  "name":            "John Doe",
  "email":           "john.doe@example.com",
  "phone":           "+15551234567",
  "parentAccountId": "<your partner accountId>"
}
Request body
name
string
required
Full legal name of the end user.
email
string
required
User’s email address. Must be unique within the same parentAccountId.
phone
string
required
Phone number in E.164 format, including country code (e.g. +15551234567).
parentAccountId
string
required
Your partner account UUID. This is the merchant account that owns all sub-accounts.
Response (200)
{
  "code": "000000",
  "message": "success",
  "data": {
    "accountId": "78ad30f2-5794-47c7-b413-62cc599ab203",
    "userId":    "1963922322985988097"
  }
}
Save accountId to your database — you’ll attach it to every subsequent call for this user.
If you call register with an email that already exists for the same parentAccountId, you’ll receive error 40001 email already exists. Look up the existing account via GET /v1/accounts?email=... before retrying.
2

Submit KYC

Cards cannot be issued until the user has passed KYC. Seismic supports two flows: bring your own KYC (submit a verified Sumsub share token) or hosted KYC via the dashboard. This guide shows the Sumsub flow.
POST /v1/accounts/{accountId}/kyc
Host: sandbox-api.seismic.systems
x-access-token: <your access token>
Content-Type: application/json

{
  "sourceType":            "sumsub",
  "sumsubShareToken":      "_act-sbx-jwt-XXXXX...",
  "ipAddress":             "203.0.113.42",
  "occupation":            "11-1011",
  "annualSalary":          "75000 USD",
  "accountPurpose":        "Living Expense",
  "expectedMonthlyVolume": "1000 USD"
}
Request body
sourceType
string
required
KYC provider. Use sumsub for the Sumsub share-token flow.
sumsubShareToken
string
required
The share token issued by Sumsub after the applicant completes your KYC flow.
ipAddress
string
IP address of the end user at the time of submission. Improves fraud scoring accuracy.
occupation
string
Occupation code (SOC 2018 format, e.g. 11-1011).
annualSalary
string
Annual salary with currency, e.g. "75000 USD".
accountPurpose
string
Purpose of the account, e.g. "Living Expense", "Business".
expectedMonthlyVolume
string
Expected monthly spend with currency, e.g. "1000 USD".
The KYC submission is asynchronous. Seismic fires a KYC.UPDATED webhook when the result is available — typically within two minutes. You can also poll the status endpoint.
3

Get KYC status

Poll this endpoint or rely on the KYC.UPDATED webhook to know when to proceed.
curl "https://sandbox-api.seismic.systems/v1/accounts/cdd/detail/$ACCOUNT_ID" \
  -H "x-access-token: $ACCESS_TOKEN"
Response while in review
{
  "code": "000000",
  "message": "success",
  "data": { "kyc": { "status": "PENDING", "caseId": "abc-123" } }
}
Response when approved
{
  "code": "000000",
  "message": "success",
  "data": { "kyc": { "status": "APPROVED" } }
}
KYC status values
statusWhat it means
NONENo KYC submitted yet.
PENDINGUnder review — wait for the webhook.
APPROVEDKYC passed. Continue to the next step.
REJECTEDKYC failed. Inspect caseId in your KYC dashboard, collect new documents from the user, and resubmit.
4

Initialize the account

Once KYC status is APPROVED, call this endpoint once to provision the account’s USD Wallet and unlock card issuance. Calling it more than once for the same account has no adverse effect.
POST /v1/accounts/{accountId}/init
Host: sandbox-api.seismic.systems
x-access-token: <your access token>
Content-Type: application/json

{}
Response (200)
{ "code": "000000", "message": "success", "data": true }
If you receive the KYC.UPDATED webhook with status=APPROVED, call this endpoint immediately from your webhook handler to automate the step entirely.

Phase B — Resource provisioning

1

List available BINs

Before creating a cardholder, confirm which BINs your account has access to. Budget cards require a type: 0 BIN.
curl "https://sandbox-api.seismic.systems/v1/card/bins?accountId=$ACCOUNT_ID" \
  -H "x-access-token: $ACCESS_TOKEN"
Response (200)
{
  "code": "000000",
  "data": [
    {
      "id":       "1997881966041939972",
      "bin":      "411111",
      "type":     0,
      "currency": "USD",
      "network":  "VISA"
    }
  ]
}
BIN type reference
typeMeaning
0Budget BIN — required for POST /v1/budget-card.
1Direct-load BIN — funded per card rather than via a shared budget.
Save the id of your preferred BIN as binId — you’ll use it when creating the cardholder and when issuing the card.
2

Create a cardholder

A cardholder is the persistent identity behind every card a user owns. Create exactly one per user and reuse the same cardholderId for all subsequent cards.
POST /v1/cardholders
Host: sandbox-api.seismic.systems
x-access-token: <your access token>
Idempotency-Key: 4b3f9e2c-0c4a-43b3-8e73-2f1ef0a3a9f1
Content-Type: application/json

{
  "accountId":        "78ad30f2-5794-47c7-b413-62cc599ab203",
  "binId":            "1997881966041939972",
  "businessModel":    "B2C_GATEWAY",
  "referenceId":      "yourapp-ch-user-12345",
  "firstName":        "John",
  "lastName":         "Doe",
  "email":            "john.doe@example.com",
  "phoneCountryCode": "1",
  "phoneNumber":      "5551234567",
  "address": {
    "addressLine1": "123 Main Street",
    "addressLine2": "Apt 4B",
    "city":         "New York",
    "state":        "NY",
    "country":      "US",
    "postalCode":   "10001"
  }
}
Request body
accountId
string
required
UUID of the user’s sub-account from Step 1.
binId
string
required
UUID of the BIN from the list endpoint. Must be a type: 0 BIN.
businessModel
string
required
Use B2C_GATEWAY for consumer cards.
referenceId
string
required
Your stable internal identifier for this cardholder (e.g. yourapp-ch-{userId}). Used to detect duplicates on retry.
firstName
string
required
First name. Letters A–Z only — no accents, hyphens, or punctuation. Combined with lastName, must be 23 characters or fewer including the space.
lastName
string
required
Last name. Same character constraints as firstName.
email
string
required
User’s email address.
phoneCountryCode
string
required
Digits only — no +. Use 1 for the US, not +1.
phoneNumber
string
required
Local phone number. Validated against Google libphonenumber555 test numbers fail.
address
object
required
Billing address for the cardholder.
Response (200)
{
  "code": "000000",
  "message": "success",
  "data": {
    "id":               "1963922322985988097",
    "status":           "PENDING",
    "accountId":        "78ad30f2-5794-47c7-b413-62cc599ab203",
    "firstName":        "John",
    "lastName":         "Doe",
    "userName":         "John Doe",
    "email":            "john.doe@example.com",
    "phoneCountryCode": "1",
    "phoneNumber":      "5551234567",
    "referenceId":      "yourapp-ch-user-12345",
    "cardBinList":      ["1997881966041939972"]
  }
}
Save data.id as the user’s cardholderId. The cardholder transitions from PENDING to APPROVED within seconds. Subscribe to the CARDHOLDER.UPDATED webhook to be notified.
First + last name combined must be 23 characters or fewer (including the space between them). This is a hard card-network limit. Strip diacritics before submitting — José must become Jose.
3

Create a budget

A budget is the USD pool that backs your user’s cards. Cards spend from the budget; if the budget balance reaches zero, authorizations decline.
POST /v1/budgets
Host: sandbox-api.seismic.systems
x-access-token: <your access token>
Idempotency-Key: 8a7c6e2d-1f4a-43b3-8e73-2f1ef0a3a9f1
Content-Type: application/json

{
  "accountId": "78ad30f2-5794-47c7-b413-62cc599ab203",
  "name":      "John's main wallet",
  "currency":  "USD"
}
Request body
accountId
string
required
UUID of the user’s sub-account.
name
string
required
Human-readable name for this budget, shown in the merchant portal.
currency
string
required
Currency code. Use USD.
Response (200)
{
  "code": "000000",
  "message": "success",
  "data": {
    "id":      "c0598084-16d9-4426-b98e-382166afb0eb",
    "balance": { "id": "0d13f168-339b-4b74-a412-07a6ababcd9c", "available": "0.00", "currency": "USD" },
    "status":  "ACTIVE"
  }
}
Save data.id as the user’s budgetId.
4

Fund the budget

A budget starts at $0.00. Move USD into it from your master merchant account before the user can spend.Step 1 — Top up the user’s USD Wallet from your master merchant poolUse POST /v1/business/transfer/external to move funds from your master merchant account into the sub-account’s USD Wallet. See API Reference → Inter-account transfers for the full parameter reference.You can check the sub-account’s USD Wallet balance at any time:
curl "https://sandbox-api.seismic.systems/v1/cards/wallets?accountId=$ACCOUNT_ID" \
  -H "x-access-token: $ACCESS_TOKEN"
Step 2 — Transfer from the USD Wallet into the budget
POST /v1/budgets/{budgetId}/transfer-in
Host: sandbox-api.seismic.systems
x-access-token: <your access token>
Idempotency-Key: f4e6c2a1-1f4a-43b3-8e73-2f1ef0a3a9f1
Content-Type: application/json

{
  "clientTransactionId": "yourapp-fund-{uuid}",
  "amount":              "100.00",
  "accountId":           "78ad30f2-5794-47c7-b413-62cc599ab203"
}
clientTransactionId
string
required
Your unique identifier for this transfer. Use a UUID. Re-using this ID returns the original response without creating a duplicate transfer.
amount
string
required
Amount in USD as a decimal string, e.g. 100.00.
accountId
string
required
UUID of the user’s sub-account.
Response (200)
{ "code": "000000", "message": "success", "data": { "transactionId": "..." } }
Verify the balance by fetching the budget:
curl "https://sandbox-api.seismic.systems/v1/budgets/$BUDGET_ID?accountId=$ACCOUNT_ID" \
  -H "x-access-token: $ACCESS_TOKEN"
{
  "code": "000000",
  "data": { "id": "...", "balance": { "available": "100.00", "currency": "USD" }, "status": "ACTIVE" }
}

Phase C — Card issuance

1

Issue the virtual card

This is the only call you repeat for each new card. Pass the accountId, binId, cardholderId, and budgetId from the previous steps. The card is created instantly in ACTIVE status, ready for online purchases.
POST /v1/budget-card
Host: sandbox-api.seismic.systems
x-access-token: <your access token>
Idempotency-Key: 9c8b7a6e-1f4a-43b3-8e73-2f1ef0a3a9f1
Content-Type: application/json

{
  "accountId":    "78ad30f2-5794-47c7-b413-62cc599ab203",
  "binId":        "1997881966041939972",
  "cardMode":     "VIRTUAL_CARD",
  "cardholderId": "1963922322985988097",
  "budgetId":     "c0598084-16d9-4426-b98e-382166afb0eb",
  "referenceId":  "yourapp-card-12345-1714000000",
  "label":        "Primary card"
}
Request body
accountId
string
required
UUID of the user’s sub-account.
binId
string
required
UUID of the BIN. Must be a type: 0 (Budget) BIN.
cardMode
string
required
VIRTUAL_CARD for a digital-only card. PHYSICAL_CARD for mailed plastic — requires additional onboarding; contact your account manager.
cardholderId
string
required
UUID from the create-cardholder step.
budgetId
string
required
UUID from the create-budget step.
referenceId
string
required
Your globally unique identifier for this card. Must be unique across all cards. Re-using one fails with error 40001. Recommended format: {your-prefix}-{userId}-{timestamp}.
label
string
Human-readable card name shown in the merchant portal. Up to 50 characters.
useType
string
Free-form tag for reporting, e.g. Online advertising, Travel.
Response (200)
{
  "code": "000000",
  "message": "success",
  "data": {
    "id":           "d8eda079-6ba7-409e-99c8-ab5f83566fbd",
    "accountId":    "78ad30f2-5794-47c7-b413-62cc599ab203",
    "userName":     "John Doe",
    "currency":     "USD",
    "bin":          "411111",
    "status":       "ACTIVE",
    "cardLastFour": "4567",
    "label":        "Primary card",
    "balanceId":    "0d13f168-339b-4b74-a412-07a6ababcd9c",
    "budgetId":     "c0598084-16d9-4426-b98e-382166afb0eb",
    "cardholderId": "1963922322985988097",
    "referenceId":  "yourapp-card-12345-1714000000",
    "cardMode":     "VIRTUAL_CARD",
    "createTime":   "1710813276127",
    "billingAddress": {
      "addressLine1": "123 Main Street",
      "addressLine2": "Apt 4B",
      "city":         "New York",
      "state":        "NY",
      "country":      "US",
      "postalCode":   "10001"
    },
    "transactionLimits": []
  }
}
Key response fields
id
string
The Seismic card UUID. Persist this as cardId — you’ll use it to show card details, freeze/unfreeze, and look up transactions.
cardLastFour
string
Last 4 digits of the PAN. Safe to display in your UI.
bin
string
First 6 digits of the PAN. Safe to display.
status
string
ACTIVE, INACTIVE, CONTROL, PENDING, or FROZEN.
transactionLimits
array
Velocity limits on the card. Empty by default. Call PUT /v1/cards/{cardId}/velocity-control to add limits by day, month, or lifetime.

What’s next?

The card is now ACTIVE and ready for online purchases. Here are the most common next steps:

Show card details

Display the full PAN, CVV, and expiry in your app without touching raw card data using the PCI Widget.

Receive spend events

Subscribe to CARD_TRANSACTION.CREATED and CARD_TRANSACTION.UPDATED for real-time authorizations and settlements.

API reference

Freeze/unfreeze cards, set velocity controls, pull transaction history, and more.
Common post-issuance operations
GoalEndpoint
Set per-card spending limitsPUT /v1/cards/{cardId}/velocity-control
Freeze or unfreeze the cardPOST /v1/cards/{cardId}/freeze / unfreeze
Pull transaction historyGET /v1/cards/transaction-list?cardId={cardId}&accountId={accountId}
Top up the budgetPOST /v1/budgets/{budgetId}/transfer-in
Cancel the card permanentlyDELETE /v1/cards/{cardId}?accountId={accountId}