SSeev PlusDocs

Payment Widget

Everything you need to know to add crypto on/off-ramp payments to your website.


What Is SeevCash?

SeevCash lets your customers buy and sell USDC (a US dollar-pegged cryptocurrency on the Stellar blockchain) using Mobile Money — directly from your website.

  • Buy USDC — Customer pays with MTN MoMo, Vodafone Cash, or AirtelTigo Money → receives USDC in their Stellar wallet
  • Sell USDC — Customer sends USDC → receives GHS in their Mobile Money wallet

You don't need to handle any blockchain logic. We take care of everything.


How It Works (User Experience)

Sell USDC Flow (Withdraw → Mobile Money Payout):

  1. Merchant backend initializes a widget session (POST /api/v1/widget/session)
  2. Merchant backend authenticates with the anchor via SEP-10
  3. Merchant backend requests a SEP-24 withdraw interactive URL with merchant session fields
  4. Customer is redirected to the interactive URL in an iframe/popup
  5. Customer completes KYC and enters Mobile Money payout details
  6. Customer sends USDC to the anchor's Stellar address with the provided memo
  7. SeevCash receives USDC → disburses GHS to customer's MoMo (1–5 minutes)
  8. Merchant receives webhook notification on completion

Quick Start (5 Minutes)

Step 1: Register Your Merchant Account

curl --location 'https://widget-backend.seevcash.com/api/v1/merchant/register' \
--header 'Content-Type: application/json' \
--data-raw '{
  "name": "Acme Payments",
  "legal_name": "Acme Payments Ltd.",
  "email": "admin@acmepay.com",
  "password": "MerchantPass123!"
}'

Response (201):

{
    "data": {
        "id": "a227bfda-6a91-4749-a360-bbbd2eeb8eff",
        "name": "Acme Payments",
        "legal_name": "Acme Payments Ltd.",
        "email": "admin@acmepay.com",
        "status": "pending",
        "tier": "starter",
        "fee_base_bps": 100,
        "fee_markup_bps": 0,
        "monthly_volume_limit": 100000,
        "current_month_volume": 0,
        "stellar_public_key": "GCGZIEFPQL3L3FDXCQKEY273QIVBNTWNANH6RBHXASVJ7SE423VTIUZL",
        "is_test_mode": false,
        "created_at": "2026-05-13T12:30:07.592877236Z",
        "updated_at": "2026-05-13T12:30:07.592877236Z"
    },
    "meta": {
        "request_id": "ffce4778-f125-4b5c-9ca7-42edfae871cb",
        "timestamp": "2026-05-13T12:30:07.720850177Z"
    }
}

Key fields:

FieldMeaning
idYour unique merchant ID
status: "pending"Becomes active after KYB verification
tier: "starter"Determines your volume limits
fee_base_bps: 100Your base fee (100 bps = 1%)
stellar_public_keyAuto-generated, used for blockchain auth behind the scenes

Step 2: Log In

curl --location 'https://widget-backend.seevcash.com/api/v1/merchant/login' \
--header 'Content-Type: application/json' \
--data-raw '{
  "email": "admin@acmepay.com",
  "password": "MerchantPass123!"
}'

Response (200):

{
    "data": {
        "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJmMjVlM2U1Zi1lODNhLTRlYmEtOTNiOS01MDQ0ZDc2NDU2NzMiLCJleHAiOjE3Nzg3NTQxNzQsImlhdCI6MTc3ODY2Nzc3NH0..."
    },
    "meta": {
        "request_id": "7e5b2ee9-f130-44e0-8487-c9135633fa23",
        "timestamp": "2026-05-13T10:22:54.108683834Z"
    }
}

The access_token is a JWT valid for 24 hours. Use it as Authorization: Bearer <token> for all merchant dashboard endpoints.


Step 3: Create an API Key

curl --location 'https://widget-backend.seevcash.com/api/v1/merchant/apikeys' \
--header 'Authorization: Bearer <your_access_token>' \
--header 'Content-Type: application/json' \
--data '{
  "key_type": "public",
  "domains": ["http://localhost:3000", "https://myapp.example.com"]
}'

Response (201):

{
    "data": {
        "api_key": {
            "id": "e16c5b6e-2c6e-47ee-98c9-7646f0eaae2f",
            "merchant_id": "f25e3e5f-e83a-4eba-93b9-5044d7645673",
            "key_type": "public",
            "key_prefix": "sv_public_07",
            "allowed_domains": [
                "http://localhost:3000",
                "https://myapp.example.com"
            ],
            "allowed_ips": [],
            "permissions": ["onramp", "offramp"],
            "rate_limit_rpm": 600,
            "is_active": true,
            "created_at": "2026-05-13T12:32:30.232150975Z"
        },
        "key": "sv_public_07386d7477d35f4243fc6b56a5d09aa58a244a742514b270d7ed2a646ca12f15"
    },
    "meta": {
        "request_id": "ad1947d6-1a0d-447f-9b22-b376c5d76beb",
        "timestamp": "2026-05-13T12:32:30.241750377Z"
    }
}

⚠️ The key field is only shown once. Store it securely.

Key types:

TypeUse ForSecurity
publicFrontend widget script (data-api-key)Domain-restricted
secretServer-to-server API callsIP-restricted recommended


API Reference

Base URL: https://widget-backend.seevcash.com

All responses are wrapped in { "data": {...}, "meta": {...} } format.


Initialize Widget Session

Creates a session for widget API calls. The widget does this automatically, but you can also call it server-side.

⚠️ The user_id must be a verified SEP-12 customer ID obtained from either the Widget Customer API or the Anchor SEP-12 flow. See Customer KYC below.

POST /api/v1/widget/session
X-API-Key: <your_api_key>
Content-Type: application/json
{
    "user_id": "6a3ce6751dbd5c0082a8d1b5"
}

Response (201):

{
    "data": {
        "session_id": "2e72ff62-9d3e-4e54-8378-fa3c9e85bd0e",
        "session_token": "0c28199e-cd8b-4ea5-8c3b-980c778944e5",
        "merchant_id": "f25e3e5f-e83a-4eba-93b9-5044d7645673",
        "expires_at": "2026-05-13T11:54:53.289405068Z"
    }
}

Sessions expire after 30 minutes. If the customer's KYC is not ACCEPTED, you'll receive a 403 KYC_NOT_APPROVED error.


Customer KYC (Verification)

Before a customer can transact (buy/sell USDC), they must pass KYC verification. SeevCash supports two flows:

FlowBest ForWho Handles KYC
Widget Customer APIMerchants who want a simple REST APIWidget handles everything
Anchor SEP-12 DirectDevelopers familiar with Stellar anchor protocolsYou interact with the anchor directly

Both flows produce a customer ID that you use as the user_id in all subsequent API calls.


The simplest way to onboard customers. You send customer details to the widget API, and it handles SEP-12 registration with the anchor behind the scenes.

Step 1: Create a Customer

curl --location 'https://widget-backend.seevcash.com/api/v1/widget/customer' \
--header 'X-API-Key: sv_secret_<your_secret_key>' \
--header 'Content-Type: application/json' \
--data-raw '{
  "first_name": "Patrick",
  "last_name": "Oduro",
  "email_address": "patrick@example.com",
  "birth_date": "1990-05-15",
  "address": "123 Main Street",
  "city": "Accra",
  "address_country_code": "GHA",
  "mobile_number": "+233244123456"
}'

Response (201):

{
    "data": {
        "id": "6a3ce6751dbd5c0082a8d1b5",
        "status": "ACCEPTED"
    },
    "meta": {
        "request_id": "ddc93e15-410e-4f68-bc99-43953f951a98",
        "timestamp": "2026-06-25T08:27:33.622249018Z"
    }
}
FieldDescription
idThe customer ID — use this as user_id in all subsequent calls
statusACCEPTED = ready to transact, NEEDS_INFO = more fields required, PROCESSING = under review

Required fields:

FieldTypeDescription
first_namestringCustomer's given name
last_namestringCustomer's family name
email_addressstringValid email address

Optional fields (improve approval speed):

FieldTypeExample
birth_datestring"1990-05-15" (YYYY-MM-DD)
addressstring"123 Main Street"
citystring"Accra"
state_or_provincestring"Greater Accra"
postal_codestring"00233"
address_country_codestring"GHA" (ISO 3166-1 alpha-3)
mobile_numberstring"+233244123456" (with country code)

Step 2: Check Customer Status

If the status is PROCESSING or NEEDS_INFO, poll this endpoint:

curl --location 'https://widget-backend.seevcash.com/api/v1/widget/customer/6a3ce6751dbd5c0082a8d1b5' \
--header 'X-API-Key: sv_secret_<your_secret_key>'

Response (200):

{
    "data": {
        "id": "6a3ce6751dbd5c0082a8d1b5",
        "status": "ACCEPTED",
        "provided_fields": {
            "first_name": { "type": "string", "description": "Given or first name", "status": "ACCEPTED" },
            "last_name": { "type": "string", "description": "Family or last name", "status": "ACCEPTED" },
            "email_address": { "type": "string", "description": "Email address", "status": "ACCEPTED" },
            "birth_date": { "type": "date", "description": "Date of birth (YYYY-MM-DD)", "status": "ACCEPTED" }
        }
    }
}

If status is NEEDS_INFO, the response includes a fields object listing what's still required:

{
    "data": {
        "id": "6a3ce6751dbd5c0082a8d1b5",
        "status": "NEEDS_INFO",
        "fields": {
            "email_address": { "type": "string", "description": "Email address" },
            "last_name": { "type": "string", "description": "Family or last name" }
        }
    }
}

To provide the missing fields, call POST /api/v1/widget/customer again with the same data plus the missing fields — the customer record will be updated (idempotent).

Step 3: Delete a Customer

If a customer requests data deletion or you need to remove them:

curl --location --request DELETE 'https://widget-backend.seevcash.com/api/v1/widget/customer/6a3ce6751dbd5c0082a8d1b5' \
--header 'X-API-Key: sv_secret_<your_secret_key>'

Response (200):

{
    "data": { "deleted": true }
}

This removes the customer from both the SeevCash anchor and the widget database. The customer ID can no longer be used.

Step 4: Use the Customer ID

Once your customer has status: "ACCEPTED", use their ID as user_id everywhere:

# Initialize session
curl -X POST 'https://widget-backend.seevcash.com/api/v1/widget/session' \
--header 'X-API-Key: sv_secret_<your_key>' \
--header 'Content-Type: application/json' \
--data '{ "user_id": "6a3ce6751dbd5c0082a8d1b5" }'

# Create orders, interactive flows, etc. — all use the same customer ID

Option B: Anchor SEP-12 Direct Flow

For developers who want direct control over the Stellar anchor's KYC protocol. You interact with the anchor at https://anchor-prod.seevcash.com using SEP-10 authentication and SEP-12 customer management.

Prerequisites

  • A Stellar keypair (your merchant's keypair from registration, or any funded Stellar account)
  • Understanding of SEP-10 (authentication) and SEP-12 (KYC)

Step 1: SEP-10 Authentication

Get a challenge transaction and sign it with your Stellar secret key:

# Get challenge
curl 'https://anchor-prod.seevcash.com/auth?account=GABC...YOUR_STELLAR_PUBLIC_KEY'

# Response: { "transaction": "<XDR_CHALLENGE>", "network_passphrase": "..." }

# Sign the challenge with your secret key and submit:
curl -X POST 'https://anchor-prod.seevcash.com/auth' \
--header 'Content-Type: application/json' \
--data '{ "transaction": "<SIGNED_XDR>" }'

# Response: { "token": "eyJhbG..." }

The token is valid for 15 minutes.

Step 2: Create Customer (PUT /customer)

curl --location --request PUT 'https://anchor-prod.seevcash.com/customer' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <SEP-10_JWT>' \
--data-raw '{
  "first_name": "Patrick",
  "last_name": "Oduro",
  "email_address": "patrick@example.com",
  "birth_date": "1990-05-15",
  "address": "123 Main Street",
  "city": "Accra",
  "address_country_code": "GHA",
  "mobile_number": "+233244123456"
}'

Response (202):

{
    "id": "6a3ce6751dbd5c0082a8d1b5"
}

Per SEP-12, PUT /customer only returns the customer ID. Query status with GET /customer.

Step 3: Check Status (GET /customer)

curl 'https://anchor-prod.seevcash.com/customer?id=6a3ce6751dbd5c0082a8d1b5' \
--header 'Authorization: Bearer <SEP-10_JWT>'

Response (200):

{
    "id": "6a3ce6751dbd5c0082a8d1b5",
    "status": "ACCEPTED",
    "provided_fields": {
        "first_name": { "type": "string", "description": "Given or first name", "status": "ACCEPTED" },
        "last_name": { "type": "string", "description": "Family or last name", "status": "ACCEPTED" },
        "email_address": { "type": "string", "description": "Email address", "status": "ACCEPTED" }
    }
}

Step 4: Use the Customer ID in Widget

The customer ID from the anchor can be used directly in the widget APIs:

curl -X POST 'https://widget-backend.seevcash.com/api/v1/widget/session' \
--header 'X-API-Key: sv_secret_<your_key>' \
--header 'Content-Type: application/json' \
--data '{ "user_id": "6a3ce6751dbd5c0082a8d1b5" }'

SEP-12 Customer Statuses

StatusMeaningAction
ACCEPTEDKYC approved — customer can transact✅ Proceed
PROCESSINGUnder review by compliance⏳ Poll periodically
NEEDS_INFOMissing required informationSubmit additional fields via PUT /customer
REJECTEDKYC permanently denied❌ Customer cannot transact

SEP-12 Field Statuses (per field)

StatusMeaning
ACCEPTEDField verified and approved
PROCESSINGField under review
REJECTEDField rejected (see error for reason)
VERIFICATION_REQUIREDField needs verification (e.g., OTP for phone)

Delete Customer (SEP-12)

curl --location --request DELETE 'https://anchor-prod.seevcash.com/customer/6a3ce6751dbd5c0082a8d1b5' \
--header 'Authorization: Bearer <SEP-10_JWT>'

Response (200):

{ "message": "customer deleted" }

Comparing the Two Flows

Widget Customer APIAnchor SEP-12 Direct
AuthAPI Key (X-API-Key)SEP-10 JWT (Stellar keypair signing)
ComplexitySimple REST callsRequires Stellar SDK & key management
Endpointwidget-backend.seevcash.comanchor-prod.seevcash.com
Customer IDSame format, interchangeableSame format, interchangeable
Best forWeb/mobile apps, fintech integrationsStellar wallets, DeFi protocols
KYC handled byWidget (automatic)You (manual SEP-10 → SEP-12 flow)

💡 Both flows produce the same customer ID format. A customer created via Option A can be queried via Option B and vice versa.


Anchor Integration (Direct SEP-24 Flow)

For merchants who want programmatic control over the payment flow — building custom UIs, triggering withdrawals from their backend, or integrating into existing apps — you can interact directly with the SeevCash Stellar Anchor using the Stellar Wallet SDK.


Deposit & Withdraw (Interactive URLs)

After completing Customer KYC, you can initiate deposit (buy USDC) and withdraw (sell USDC) flows. There are two approaches:

ApproachAuthBest For
Widget API (recommended)API Key (X-API-Key)Simple server-to-server integration
Anchor SEP-24 DirectSEP-10 JWT + session fieldsStellar-native wallets, full protocol control

Both return an interactive URL that you open in an iframe or popup for the customer to complete the payment.


The widget handles SEP-10 authentication, session management, and anchor communication. You just need your API keys and a verified customer ID.

Prerequisites

CredentialHow to GetExample
sv_secret_ keyPOST /merchant/apikeys with key_type: "secret"sv_secret_4a95a7cc...
sv_public_ keyPOST /merchant/apikeys with key_type: "public"sv_public_61f8ac8b...
Customer IDPOST /widget/customer (must be ACCEPTED)6a3cec4b21ea9c49b5d34534

⚠️ The secret key goes in the X-API-Key header (server-to-server). The public key goes in the request body api_key field (used to generate the widget token).

Withdraw (Sell USDC → Receive Mobile Money)

Customer sends USDC to the anchor, receives GHS in their Mobile Money wallet.

curl --location 'https://widget-backend.seevcash.com/api/v1/widget/withdraw/interactive' \
--header 'X-API-Key: sv_secret_4a95a7cc50961ec5f0b6329c2b5aefb767a68ee3cf5b5133344a18549cad1d42' \
--header 'Content-Type: application/json' \
--data '{
    "asset_code": "USDC",
    "user_id": "6a3cec4b21ea9c49b5d34534",
    "api_key": "sv_public_61f8ac8b75e8a55a16cdea49d2eff4392cf557b9c22df24ecca0eb07de2cdaba",
    "onchain_amount": 1
}'

Request fields:

FieldTypeRequiredDescription
asset_codestringAlways "USDC"
user_idstringSEP-12 customer ID (must be ACCEPTED)
api_keystringYour public API key (sv_public_...)
onchain_amountnumberOptionalAmount of USDC to sell. If omitted, customer enters in the interactive UI

Response (200):

{
    "data": {
        "url": "https://exchange.seevcash.com/interactive?token=eyJhbG...",
        "id": "05c6ce07-18c8-48f8-b7b1-e5d66b735d3d",
        "type": "interactive_customer_info_needed"
    },
    "meta": {
        "request_id": "d3fb956f-62d9-4e62-8b59-4c26e48674f6",
        "timestamp": "2026-06-25T09:26:16.375369413Z"
    }
}

Deposit (Buy USDC with Mobile Money)

Customer pays with Mobile Money, receives USDC in their Stellar wallet.

curl --location 'https://widget-backend.seevcash.com/api/v1/widget/deposit/interactive' \
--header 'X-API-Key: sv_secret_4a95a7cc50961ec5f0b6329c2b5aefb767a68ee3cf5b5133344a18549cad1d42' \
--header 'Content-Type: application/json' \
--data '{
    "asset_code": "USDC",
    "user_id": "6a3cec4b21ea9c49b5d34534",
    "api_key": "sv_public_f69d93fb31adcb64d9f85d823be4236048e9bdc37bca4d5950182aa6d9b619fb",
    "fiat_amount": 13,
    "destination_address": "GCGES3SODXJX6RYF2ATRQIA5GLWDXTEXR6QWX3JERVCDY4EIFEMFB55O"
}'

Request fields:

FieldTypeRequiredDescription
asset_codestringAlways "USDC"
user_idstringSEP-12 customer ID (must be ACCEPTED)
api_keystringYour public API key (sv_public_...)
fiat_amountnumberOptionalAmount in GHS to spend. If omitted, customer enters in the interactive UI
destination_addressstringOptionalStellar address to receive USDC. If omitted, customer enters in the UI

Response (200):

{
    "data": {
        "url": "https://exchange.seevcash.com/interactive?token=eyJhbG...",
        "id": "fa80ebf4-b431-42ce-a255-e3680e221e09",
        "type": "interactive_customer_info_needed"
    },
    "meta": {
        "request_id": "09193866-b809-4834-a9d8-682bf44be9ac",
        "timestamp": "2026-06-25T09:27:03.127272637Z"
    }
}

Response Fields

FieldDescription
urlInteractive URL — open in iframe, popup, or redirect the customer here
idTransaction ID — use to track status via GET /transaction?id=...
typeAlways "interactive_customer_info_needed"

What Happens After Getting the URL

  1. Open the url in an iframe, popup, or full-page redirect
  2. Customer selects their Mobile Money provider (MTN, Vodafone, AirtelTigo)
  3. Customer enters their phone number and confirms payment
  4. For deposits: Customer approves the MoMo prompt → receives USDC (1–4 min)
  5. For withdrawals: Customer sees anchor's Stellar address + memo → sends USDC → receives GHS (1–5 min)
  6. You receive a webhook when the transaction completes

Option B: Anchor SEP-24 Direct Flow

For developers building Stellar-native wallets or who need full protocol control. You interact directly with the anchor at https://anchor-prod.seevcash.com.

💡 We recommend using the Stellar Wallet SDK for SEP-24 integration. It handles SEP-10 authentication, token management, and transaction tracking automatically.

Prerequisites

  • A Stellar keypair (your merchant's keypair from registration)
  • A widget session (POST /api/v1/widget/session)
  • A verified customer ID (SEP-12 ACCEPTED)

Install the Stellar Wallet SDK

npm install @stellar/typescript-wallet-sdk @stellar/stellar-sdk
import {
    Wallet,
    SigningKeypair,
    StellarConfiguration,
} from '@stellar/typescript-wallet-sdk';

const ANCHOR_HOME_DOMAIN = 'anchor-prod.seevcash.com';

async function initiateWithdraw(
    signerSecret: string,   // Your merchant's Stellar secret key
    merchantId: string,     // From merchant registration
    sessionId: string,      // From POST /widget/session
    sessionToken: string,   // From POST /widget/session
    apiKey: string,         // Your public key (sv_public_...)
    userId: string,         // SEP-12 customer ID (ACCEPTED)
) {
    const accountKp = SigningKeypair.fromSecret(signerSecret);

    const wallet = new Wallet({
        stellarConfiguration: StellarConfiguration.MainNet(),
    });
    const anchor = wallet.anchor({ homeDomain: ANCHOR_HOME_DOMAIN });

    // Step 1: SEP-10 Authentication (SDK handles challenge signing)
    const sep10 = await anchor.sep10();
    const authToken = await sep10.authenticate({ accountKp });

    // Step 2: SEP-24 Withdraw
    const sep24 = await anchor.sep24();
    const { url, id, type } = await sep24.withdraw({
        assetCode: 'USDC',
        authToken,
        extraFields: {
            merchant_id: merchantId,
            session_id: sessionId,
            session_token: sessionToken,
            api_key: apiKey,
            user_id: userId,
        },
    });

    // url → open in iframe/popup for customer
    // id  → transaction ID for tracking
    return { url, id, type };
}

async function initiateDeposit(
    signerSecret: string,
    merchantId: string,
    sessionId: string,
    sessionToken: string,
    apiKey: string,
    userId: string,
    stellarAccount: string,  // Customer's Stellar address to receive USDC
) {
    const accountKp = SigningKeypair.fromSecret(signerSecret);

    const wallet = new Wallet({
        stellarConfiguration: StellarConfiguration.MainNet(),
    });
    const anchor = wallet.anchor({ homeDomain: ANCHOR_HOME_DOMAIN });

    const sep10 = await anchor.sep10();
    const authToken = await sep10.authenticate({ accountKp });

    const sep24 = await anchor.sep24();
    const { url, id, type } = await sep24.deposit({
        assetCode: 'USDC',
        authToken,
        destinationAccount: stellarAccount,
        extraFields: {
            merchant_id: merchantId,
            session_id: sessionId,
            session_token: sessionToken,
            api_key: apiKey,
            user_id: userId,
        },
    });

    return { url, id, type };
}

Track Transaction Status with SDK

async function checkTransaction(signerSecret: string, transactionId: string) {
    const accountKp = SigningKeypair.fromSecret(signerSecret);
    const wallet = new Wallet({ stellarConfiguration: StellarConfiguration.MainNet() });
    const anchor = wallet.anchor({ homeDomain: ANCHOR_HOME_DOMAIN });

    const sep10 = await anchor.sep10();
    const authToken = await sep10.authenticate({ accountKp });

    const sep24 = await anchor.sep24();
    const tx = await sep24.getTransactionBy({ authToken, id: transactionId });

    console.log(tx.status);  // "completed", "pending_user_transfer_start", etc.
    return tx;
}

Required extraFields

FieldTypeDescription
merchant_idstringYour merchant ID from registration
session_idstringFrom POST /widget/session response
session_tokenstringFrom POST /widget/session response
api_keystringYour public API key (sv_public_...)
user_idstringSEP-12 customer ID (must be ACCEPTED)

⚠️ All fields are required on mainnet. Requests without them return 400 Bad Request. On testnet (anchor.seevcash.com), these fields are optional for easier development.

Getting Session Credentials

Before calling the anchor, create a widget session:

curl -X POST 'https://widget-backend.seevcash.com/api/v1/widget/session' \
--header 'X-API-Key: sv_secret_<your_key>' \
--header 'Content-Type: application/json' \
--data '{ "user_id": "6a3cec4b21ea9c49b5d34534" }'

# Response:
# { "data": { "session_id": "...", "session_token": "...", "merchant_id": "...", "expires_at": "..." } }

Advanced: Raw HTTP Calls (without SDK)

If you can't use the SDK, here are the raw endpoints. You'll need to handle SEP-10 authentication manually.

SEP-10 Authentication
# 1. Get challenge
curl 'https://anchor-prod.seevcash.com/auth?account=<YOUR_STELLAR_PUBLIC_KEY>'
# Response: { "transaction": "<XDR_CHALLENGE>", "network_passphrase": "..." }

# 2. Sign the XDR with your secret key and submit
curl -X POST 'https://anchor-prod.seevcash.com/auth' \
--header 'Content-Type: application/json' \
--data '{ "transaction": "<SIGNED_XDR>" }'
# Response: { "token": "eyJhbG..." }  (valid 15 minutes)
Deposit Interactive
curl --location 'https://anchor-prod.seevcash.com/transactions/deposit/interactive' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <SEP-10_JWT>' \
--data-raw '{
  "asset_code": "USDC",
  "account": "GCGES3SODXJX6RYF2ATRQIA5GLWDXTEXR6QWX3JERVCDY4EIFEMFB55O",
  "amount": "13",
  "merchant_id": "d92e377f-2456-4186-b6a5-cbce930a6219",
  "session_id": "5900c14c-a19f-49df-abbe-666cef7d5593",
  "session_token": "d345545a-951d-4ebe-b7e3-d7050a120436",
  "api_key": "sv_public_f69d93fb31adcb64d9f85d823be4236048e9bdc37bca4d5950182aa6d9b619fb",
  "user_id": "6a3cec4b21ea9c49b5d34534"
}'
Withdraw Interactive
curl --location 'https://anchor-prod.seevcash.com/transactions/withdraw/interactive' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <SEP-10_JWT>' \
--data-raw '{
  "asset_code": "USDC",
  "account": "GA2E5D24D2LCGVA3SVVKDP64OTN2M2NLUWRDYINB352HW35ABZ66MPVR",
  "amount": "1",
  "merchant_id": "d92e377f-2456-4186-b6a5-cbce930a6219",
  "session_id": "e70d3556-4d6b-47fe-8d33-bacd17c9cab1",
  "session_token": "cc7fad85-b9ce-48de-bdfb-89d3d87ab9fe",
  "api_key": "sv_public_61f8ac8b75e8a55a16cdea49d2eff4392cf557b9c22df24ecca0eb07de2cdaba",
  "user_id": "6a3cec4b21ea9c49b5d34534"
}'
Request Fields (Both Endpoints)
FieldTypeRequired (Mainnet)Description
asset_codestring"USDC"
accountstringOptionalStellar public key. Defaults to JWT's account
amountstringOptionalAmount (fiat for deposit, USDC for withdraw)
merchant_idstringYour merchant ID
session_idstringFrom POST /widget/session
session_tokenstringFrom POST /widget/session
api_keystringYour public API key (sv_public_...)
user_idstringSEP-12 customer ID (must be ACCEPTED)
quote_idstringOptionalFrom SEP-38 quote (for guaranteed rates)
langstringOptionalLanguage code (default: "en")
Response
{
    "type": "interactive_customer_info_needed",
    "url": "https://exchange.seevcash.com/interactive?token=eyJhbG...",
    "id": "05c6ce07-18c8-48f8-b7b1-e5d66b735d3d"
}
Track Transaction
curl 'https://anchor-prod.seevcash.com/transaction?id=<TRANSACTION_ID>' \
--header 'Authorization: Bearer <SEP-10_JWT>'

Transaction Status Flow

Deposit:  incomplete → pending_user_transfer_start → pending_anchor → pending_stellar → completed
Withdraw: incomplete → pending_user_transfer_start → pending_external → pending_payout_confirmation → completed
StatusMeaningWhat's Happening
incompleteInteractive UI not yet completedCustomer hasn't finished the form
pending_user_transfer_startWaiting for customer actionDeposit: awaiting MoMo approval. Withdraw: awaiting USDC transfer
pending_anchorAnchor processingFiat received, preparing crypto delivery
pending_stellarBlockchain transaction submittedUSDC sent, awaiting confirmation
pending_externalCrypto received by anchorUSDC received, initiating fiat payout
pending_payout_confirmationFiat payout in progressMobile Money disbursement initiated
completedDone ✅Transaction finished successfully
expiredTimed outCustomer didn't complete within window
errorFailedSee message field for details

Network Configuration

EnvironmentWidget BackendAnchor DomainNetwork
Productionwidget-backend.seevcash.comanchor-prod.seevcash.comStellar Mainnet
Testnetwidget-backend.seevcash.comanchor.seevcash.comStellar Testnet

Comparing Widget vs Anchor Direct for Interactive Flows

Widget APIAnchor SEP-24 (SDK)
EndpointPOST /widget/deposit/interactiveSDK: sep24.deposit() / sep24.withdraw()
AuthX-API-Key: sv_secret_...SEP-10 (SDK handles automatically)
Session mgmtAutomaticManual (create session, pass fields)
LanguageAny (REST API)TypeScript/JavaScript
When to useServer-to-server, any languageStellar wallet apps, JS/TS projects
Same interactive URL?✅ Yes✅ Yes
Same transaction ID?✅ Yes✅ Yes

💡 Both approaches generate the same interactive URL pointing to exchange.seevcash.com. The customer experience is identical regardless of which method you use.


Get Widget Config

GET /api/v1/widget/config
X-API-Key: <your_api_key>

Response (200):

{
    "data": {
        "merchant_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
        "theme": { "primary_color": "#4F46E5", "border_radius": "8px" },
        "allowed_coins": ["USDC"],
        "redirect_url": "https://mystore.com/payment-complete"
    }
}

Update Widget Config

PUT /api/v1/merchant/widget-config
Authorization: Bearer <access_token>
Content-Type: application/json
{
    "theme": { "primary_color": "#10B981", "border_radius": "12px" },
    "allowed_coins": ["USDC"],
    "redirect_url": "https://mystore.com/thank-you"
}

List Merchant Orders

GET /api/v1/merchant/orders?limit=20&cursor=
Authorization: Bearer <access_token>

Response (200):

{
    "data": [
        {
            "id": "ord_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
            "status": "completed",
            "fiat_currency": "GHS",
            "fiat_amount": 100.0,
            "crypto_currency": "USDC",
            "crypto_amount": 6.45,
            "payment_method": "mobile_money",
            "created_at": "2026-05-13T10:30:00Z"
        }
    ],
    "next_cursor": "ord_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "has_more": false
}

Other Merchant Dashboard Endpoints

EndpointMethodDescription
/api/v1/merchant/profileGETView your merchant profile
/api/v1/merchant/apikeys/:idDELETERevoke an API key
/api/v1/merchant/kyb/submitPOSTSubmit KYB (Know Your Business) documents
/api/v1/merchant/kyb/statusGETCheck KYB verification status

All require Authorization: Bearer <access_token>.


Required Headers

HeaderUsed InDescription
X-API-KeyWidget endpointsYour merchant API key
X-Session-IdSession-protected endpointsFrom /widget/session response
X-Session-TokenSession-protected endpointsFrom /widget/session response
X-Idempotency-KeyOrder creationUnique UUID to prevent duplicates
AuthorizationDashboard endpointsBearer <access_token> from login
Content-TypeAll POST/PUTapplication/json

Error Responses

All errors follow this format:

{
    "error": {
        "code": "VALIDATION_ERROR",
        "message": "fiat_amount must be greater than 0"
    }
}
CodeHTTP StatusMeaning
VALIDATION_ERROR400Request body failed validation
MISSING_HEADER400Required header missing (e.g., X-Idempotency-Key)
UNAUTHORIZED401Invalid or expired API key / session / token
FORBIDDEN403Domain not in allowed list
NOT_FOUND404Order or resource not found
DUPLICATE_ORDER409Idempotency key already used
PHONE_NOT_VERIFIED422Phone number hasn't been OTP-verified
QUOTE_EXPIRED422Quote expired, request a new one
RATE_LIMITED429Too many requests
INTERNAL_ERROR500Something went wrong on our end

Transaction Statuses

StatusMeaning
pending_user_transfer_startWaiting for customer to complete payment
pending_anchorFiat received, crypto delivery in progress
pending_stellarCrypto sent, awaiting blockchain confirmation
pending_externalCrypto received, fiat payout initiated
pending_payout_confirmationFiat payout in progress
completedTransaction finished successfully
failedSomething went wrong
expiredCustomer didn't complete within the time window

Webhooks

Configure a webhook URL in your merchant dashboard for server-side notifications.

Payload Example:

{
    "event": "order.completed",
    "order_id": "ord_abc123",
    "type": "onramp",
    "fiat_amount": "100.00",
    "fiat_currency": "GHS",
    "crypto_amount": "6.45",
    "crypto_currency": "USDC",
    "destination_address": "GABCD...XYZ",
    "timestamp": "2026-05-13T10:30:00Z"
}

Security Headers:

HeaderDescription
X-Webhook-SignatureHMAC-SHA256 signature of the payload body
X-Webhook-TimestampUnix timestamp when sent

Verify using your webhook secret (found in dashboard).

Events:

EventDescription
order.completedCrypto delivered (onramp) or fiat paid out (offramp)
order.failedPayment failed or declined
order.expiredPayment window timed out

Retry Policy:

If your endpoint returns non-2xx, we retry:

  1. Immediate → 2. 10 seconds → 3. 1 minute → 4. 1 hour → 5. 4 hours

After 5 failed attempts, delivery is marked exhausted.


Supported Payment Methods

MethodBuySellSpeed
MTN Mobile Money1–4 min
Vodafone Cash1–4 min
AirtelTigo Money1–4 min
Bank Transfer🚧🚧Coming Soon

Supported Assets

AssetNetworkDescription
USDCStellarUS Dollar-pegged stablecoin (1 USDC ≈ $1)

Fees

Fee TypeDescription
Platform feePercentage of transaction (your fee_base_bps + fee_markup_bps)
Network feeStellar transaction fee (fractions of a cent)
Exchange spreadBuilt into the quoted rate

All fees are shown to the customer before they confirm.


Security

  • All data in transit uses TLS/HTTPS
  • The widget handles all sensitive payment details — nothing touches your servers
  • Customer phone numbers are OTP-verified before any payment
  • Idempotency keys prevent duplicate charges
  • API keys can be scoped to specific domains and IP addresses
  • Webhooks are HMAC-SHA256 signed for verification

API Key Best Practices

  • Use public keys for frontend widget, secret keys for server-to-server
  • Restrict keys to your allowed domains and IPs
  • Never expose secret keys in client-side code
  • Use separate keys for development and production
  • Rotate keys periodically

Testing

Use test mode during development:

  • Stellar testnet (no real money moves)
  • Mobile Money prompts are simulated
  • All flows work identically to production

Switch to your live API key when ready to go live.


FAQ

Q: Do I need to understand blockchain? A: No. Add the script tag, receive webhooks. We handle everything else.

Q: What if a payment fails? A: No crypto is sent, no money deducted. Customer can retry.

Q: How fast are transactions? A: 1–4 minutes for buying, 1–5 minutes for selling.

Q: Can I customize the widget? A: Yes — theme colors, allowed coins, and redirect URLs via the widget config API.

Q: Minimum/maximum amounts? A: Configurable per merchant during onboarding.

Q: What if a customer doesn't have a Stellar wallet? A: They need one to receive USDC. Recommend Lobstr or StellarX.


Support


Quick Start Checklist

  • Register merchant account
  • Log in and create API key (store it securely!)
  • Create a customer via /widget/customer (KYC verification)
  • Confirm customer status is ACCEPTED
  • Initialize widget session with the customer ID as user_id
  • Test a buy and sell flow
  • Configure webhook endpoint
  • Verify webhook signatures
  • Switch to live API key
  • Go live 🚀

On this page

What Is SeevCash?How It Works (User Experience)Sell USDC Flow (Withdraw → Mobile Money Payout):Quick Start (5 Minutes)Step 1: Register Your Merchant AccountStep 2: Log InStep 3: Create an API KeyAPI ReferenceInitialize Widget SessionCustomer KYC (Verification)Option A: Widget Customer API (Recommended)Step 1: Create a CustomerStep 2: Check Customer StatusStep 3: Delete a CustomerStep 4: Use the Customer IDOption B: Anchor SEP-12 Direct FlowPrerequisitesStep 1: SEP-10 AuthenticationStep 2: Create Customer (PUT /customer)Step 3: Check Status (GET /customer)Step 4: Use the Customer ID in WidgetSEP-12 Customer StatusesSEP-12 Field Statuses (per field)Delete Customer (SEP-12)Comparing the Two FlowsAnchor Integration (Direct SEP-24 Flow)Deposit & Withdraw (Interactive URLs)Option A: Widget Interactive API (Recommended)PrerequisitesWithdraw (Sell USDC → Receive Mobile Money)Deposit (Buy USDC with Mobile Money)Response FieldsWhat Happens After Getting the URLOption B: Anchor SEP-24 Direct FlowPrerequisitesInstall the Stellar Wallet SDKComplete Flow with SDK (Recommended)Track Transaction Status with SDKRequired extraFieldsGetting Session CredentialsAdvanced: Raw HTTP Calls (without SDK)SEP-10 AuthenticationDeposit InteractiveWithdraw InteractiveRequest Fields (Both Endpoints)ResponseTrack TransactionTransaction Status FlowNetwork ConfigurationComparing Widget vs Anchor Direct for Interactive FlowsGet Widget ConfigUpdate Widget ConfigList Merchant OrdersOther Merchant Dashboard EndpointsRequired HeadersError ResponsesTransaction StatusesWebhooksPayload Example:Security Headers:Events:Retry Policy:Supported Payment MethodsSupported AssetsFeesSecurityAPI Key Best PracticesTestingFAQSupportQuick Start Checklist