Seev 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": "payments@acmepay.com",
  "password": "MerchantPass123!"
}'

Response (201):

{
    "data": {
        "id": "a227bfda-6a91-4749-a360-bbbd2eeb8eff",
        "name": "Acme Payments",
        "legal_name": "Acme Payments Ltd.",
        "email": "payments@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": "payments@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.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.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.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.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.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.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.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_codestring✅Always "USDC"
user_idstring✅SEP-12 customer ID (must be ACCEPTED)
api_keystring✅Your 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_codestring✅Always "USDC"
user_idstring✅SEP-12 customer ID (must be ACCEPTED)
api_keystring✅Your 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.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.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

All five fields below are required for a production integration and must be sent on every deposit and withdraw request.

FieldTypeRequiredDescription
merchant_idstring✅ RequiredYour merchant ID from registration
session_idstring✅ RequiredFrom POST /widget/session response
session_tokenstring✅ RequiredFrom POST /widget/session response
api_keystring✅ RequiredYour public API key (sv_public_...)
user_idstring✅ RequiredSEP-12 customer ID (must be ACCEPTED)

⚠️ Omitting any of these returns 400 Bad Request (e.g. api_key is required) and no transaction is created. While experimenting against the testnet host they may be accepted when absent, but do not rely on that — build and test with all five present so your integration behaves identically in production.

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.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.seevcash.com/auth' \
--header 'Content-Type: application/json' \
--data '{ "transaction": "<SIGNED_XDR>" }'
# Response: { "token": "eyJhbG..." }  (valid 15 minutes)
Deposit Interactive
curl --location 'https://anchor.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.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)
FieldTypeRequiredDescription
asset_codestring✅ Required"USDC"
merchant_idstring✅ RequiredYour merchant ID
session_idstring✅ RequiredFrom POST /widget/session
session_tokenstring✅ RequiredFrom POST /widget/session
api_keystring✅ RequiredYour public API key (sv_public_...)
user_idstring✅ RequiredSEP-12 customer ID (must be ACCEPTED)
accountstringOptionalStellar public key. Defaults to JWT's account
amountstringOptionalAmount (fiat for deposit, USDC for withdraw)
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.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.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 Money✅✅1–4 min
Vodafone Cash✅✅1–4 min
AirtelTigo Money✅✅1–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