Who This Guide Is For

New engineering teams integrating PayCA for the first time. You should already have:

  • A workstation with Go 1.23+ and curl or an API client such as Postman/Insomnia.
  • Network access to the sandbox base URL shared by your PayCA account manager.
  • Client credentials (x-client-id, x-client-secret) provisioned for the sandbox.

If you are renewing an existing integration, skip directly to Verify the Sandbox.

Step 1 - Configure Environment Variables

Store your sandbox credentials in environment variables or your preferred secrets manager so they never appear in plain-text scripts.

export PAYCA_BASE_URL="https://api.sandbox.payca.io"
export PAYCA_CLIENT_ID="6f1dbe35-43f7-466a-9941-1c01c5f8a6e7"
export PAYCA_CLIENT_SECRET="9a025859-1d2d-4c0f-90f5-28707c0b9d56"

Replace the sample values with the credentials you received from PayCA.

Step 2 - Verify the Sandbox

Check that your credentials work and the API is reachable.

curl -s \
  -H "x-client-id: $PAYCA_CLIENT_ID" \
  -H "x-client-secret: $PAYCA_CLIENT_SECRET" \
  "$PAYCA_BASE_URL/health"

A healthy response reports the API build SHA and the database connection status. Capture the X-Request-ID header for support conversations.

Step 3 - Register Webhook Endpoints

Webhooks mirror every change to cards, accounts, and users. Each subscription handles exactly one event type, so call the endpoint once per type you want to receive (type = card, account, or user corresponds to the card_transaction, account_transaction, and user_account_transaction feeds).

curl -s -X POST "$PAYCA_BASE_URL/v1/webhooks" \
  -H "Content-Type: application/json" \
  -H "x-client-id: $PAYCA_CLIENT_ID" \
  -H "x-client-secret: $PAYCA_CLIENT_SECRET" \
  -d '{
    "url": "https://hooks.dev.example.com/payca/card",
    "type": "card"
  }'

Repeat the request with "type": "account" and "type": "user" (optionally pointing to separate URLs) to capture ledger and user wallet events. Each response returns a webhook id; persist every identifier so you can delete or resend deliveries later.

Step 4 - Pick a Master Funding Account

Issued cards and user wallets are funded from your master (primary client) accounts. List them with GET /v2/accounts, then pick an account in the currency you want to issue or fund.

curl -s "$PAYCA_BASE_URL/v2/accounts" \
  -H "x-client-id: $PAYCA_CLIENT_ID" \
  -H "x-client-secret: $PAYCA_CLIENT_SECRET"

Response snippet:

{
  "accounts": [
    {
      "id": "c1bb6c19-3f9c-4cf0-9a08-5f2d00d021f1",
      "currency": "USD",
      "balance": { "available": "125000.00", "pending": "0.00" },
      "status": "active",
      "bins": [/* enabled BINs for this currency */]
    }
  ]
}

Use accounts[].id as:

  • accountId when issuing or topping up cards.
  • fromAccountId when transferring into a user wallet via POST /v1/users/transfer.

Step 5 - Issue a Card

Create a card by providing the funding account, target BIN, and initial balance. Include an idempotencyKey so failed retries remain safe.

curl -s -X POST "$PAYCA_BASE_URL/v1/cards" \
  -H "Content-Type: application/json" \
  -H "x-client-id: $PAYCA_CLIENT_ID" \
  -H "x-client-secret: $PAYCA_CLIENT_SECRET" \
  -d '{
        "accountId": "c1bb6c19-3f9c-4cf0-9a08-5f2d00d021f1",
        "bin": "411111",
        "balance": "50.00",
        "externalUserId": "crm-98231",
        "idempotencyKey": "issue-demo-001"
     }'

The response returns the cardId, current balance snapshot, product code, and masked PAN. Store the cardId together with the accountId you debited.

Request field cheatsheet:

Field Required Purpose
accountId Yes Account to debit (client or user).
bin Yes Six-digit BIN allocated to your tenant.
balance Yes Opening balance in card currency.
externalUserId No Echoed in downstream webhooks.
idempotencyKey Strongly recommended Ensures retries remain safe.

Step 6 - Retrieve Sensitive Card Data (Optional)

If your PCI process requires access to the PAN and CVV, fetch them once and immediately vault them.

curl -s "$PAYCA_BASE_URL/v1/cards/<card-id>/sensitive" \
  -H "x-client-id: $PAYCA_CLIENT_ID" \
  -H "x-client-secret: $PAYCA_CLIENT_SECRET"

Step 7 - Fund the Card

You can add additional balance to the card at any time from any account you control (client or user):

curl -s -X POST "$PAYCA_BASE_URL/v1/cards/<card-id>/topup" \
  -H 'Content-Type: application/json' \
  -H "x-client-id: $PAYCA_CLIENT_ID" \
  -H "x-client-secret: $PAYCA_CLIENT_SECRET" \
  -d '{
        "accountID": "c1bb6c19-3f9c-4cf0-9a08-5f2d00d021f1",
        "amount": "75.00",
        "idempotencyKey": "card-topup-75"
     }'

Ensure the source account has enough available balance before calling the endpoint.

accountID and amount align with the CardTopUpRequest schema; reuse the same fields when calling /v1/cards/{id}/withdraw.

Step 8 - Run a Transaction End-to-End

Use the sandbox helper endpoint to simulate card flow. Substitute the cardId and currency from earlier steps.

curl -s -X POST "$PAYCA_BASE_URL/sandbox/transactions" \
  -H "Content-Type: application/json" \
  -H "x-client-id: $PAYCA_CLIENT_ID" \
  -H "x-client-secret: $PAYCA_CLIENT_SECRET" \
  -d '{
    "cardId": "<card-id>",
    "currency": "USD",
    "type": "authorization",
    "amount": "42.55"
  }'

Follow it with a settle request using the returned linkedId. Confirm that webhooks fire and ledger balances adjust as expected.

Step 9 - Instrument Observability

  • Log every X-Request-ID and x-signature value from webhook deliveries.
  • Use the trace_id field provided by PayCA support to correlate ledger changes with upstream provider events.
  • Surface metrics: authorization success rate, decline reasons, average settlement time, and webhook processing latency.

Step 10 - Harden for Production

Checklist Description
Rotate credentials Generate separate secrets per environment and service.
Enforce MTLS for webhooks Restrict inbound IPs and verify certificates.
Set idempotency keys Supply keys on every transfer, users API call, and payout.
Run load tests Replay sandbox scenarios at production volume to validate webhook retries.
Map ledger accounts Document every PayCA account ID alongside your ERP counterpart.

Step 11 - (Optional) Create a User

If you plan to expose user wallets or need user-specific fee schedules, create users after you validate the core card pipeline. Each user gets a ledger wallet (userAccountId) you can fund from your master accounts via POST /v1/users/transfer. You can set status during creation (defaults to pending); switch to active via PATCH /v1/users/{id}/status before allowing transfers.

curl -s -X POST "$PAYCA_BASE_URL/v1/users" \
  -H "Content-Type: application/json" \
  -H "x-client-id: $PAYCA_CLIENT_ID" \
  -H "x-client-secret: $PAYCA_CLIENT_SECRET" \
  -d '{
        "userId": "c0ffee00-feed-face-cafe-babecafecafe",
        "status": "pending",
        "bins": [
          {
            "bin": "411111",
            "currencyCode": "USD",
            "provider": "visa",
            "settings": { "minCardBalance": "25.00" },
            "isTokenizable": true
          }
        ],
        "meta": {"segment": "testers"}
     }'

Persist the returned userId and userAccountId (also exposed as id and account.id in GET /v1/users/{id}) if you intend to lock funds or top up via /v1/users/transfer. Transfers are permitted only for active users.

Where To Go Next

When you are confident in sandbox results, request production credentials. The deployment checklist in the Go-Live Runbook ensures every dependency is ready before switching environments.

Quick Reference

Step Endpoint(s) Notes
Sandbox health GET /health Confirms credentials and platform reachability.
Register hooks POST /v1/webhooks Capture card_transaction + account_transaction early.
Prepare funding GET /v2/accounts List master accounts and confirm balances/BINs before you debit.
Issue card POST /v1/cards Provide accountId, bin, balance, and idempotency key.
Operate card POST /v1/cards/{id}/topup, /withdraw, /freeze, /unfreeze, DELETE /v1/cards/{id} Manage lifecycle and liquidity.
Observe activity /sandbox/transactions, GET /v1/cards/{id}/transactions, webhooks Use referenceId to reconcile across feeds.