> ## Documentation Index
> Fetch the complete documentation index at: https://developer.tazapay.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart: Receive Your First Payment

> Create a collection account, receive a simulated payment, and see the funds credited to your balance — end to end on sandbox, in about 15 minutes.

By the end of this guide you will have provisioned a Virtual Account via API, simulated an incoming bank transfer on sandbox, received the `collect.succeeded` webhook, fetched the collect, and confirmed the credit on your balance. You need two things before starting: a sandbox account with API keys ([Get Started with Tazapay](/getting-started/overview/get-started-with-tazapay)) and an entity — no real onboarding needed on sandbox, you can [create an entity](/api-reference/tazapay-api/create-entity) and [simulate its approval](/api-reference/tazapay-api/simulate-entity-status-in-sandbox) directly. Everything below runs against sandbox, so no real money moves.

This walkthrough uses a Singapore SGD Virtual Account. The identical flow applies to Stablecoin Wallets — swap the payload as shown in [Requesting via API](/collection-accounts/requesting-for-vas/api) and a deposit address replaces the bank details.

## The flow at a glance

1. **Provision the account** — `POST /v3/collection_account`
2. **Account enabled** — the enablement request succeeds and `status` flips to `enabled`
3. **Fetch account details** — the bank coordinates you give your payer
4. **Payer transfers funds** — a normal domestic transfer, or SWIFT, or an on-chain send
5. **Collect created & screened** — Tazapay creates a collect and runs compliance screening
6. **Collect succeeds** — `collect.succeeded` fires
7. **Balance credited** — funds land in your Tazapay balance, converted if needed

<Steps>
  <Step title="Set up authentication">
    The Tazapay API uses HTTP Basic authentication: your `API_Key` is the username and your `API_Secret` is the password, joined with a colon, Base64-encoded, and sent as `Authorization: Basic <value>`. See [Authentication](/api-reference/api-overview/authentication) for the full breakdown.

    All calls in this guide use the sandbox base URL. See [Endpoints and Environments](/api-reference/api-overview/endpoints-and-environments).

    ```bash Sandbox base URL theme={null}
    https://service-sandbox.tazapay.com
    ```

    `curl -u` performs the Basic encoding for you, so the examples below stay copy-pasteable:

    ```bash Set your credentials theme={null}
    export TZP_KEY="your_api_key"
    export TZP_SECRET="your_api_secret"
    export TZP_BASE="https://service-sandbox.tazapay.com"
    ```
  </Step>

  <Step title="Discover what you can create">
    Before creating anything, ask the Metadata API what your account is actually allowed to provision. This returns the payment method types, currencies, rails, and transfer limits available to you.

    ```bash Request theme={null}
    curl -X GET "$TZP_BASE/v3/metadata/collection_accounts/virtual_account?country=SG&currencies=SGD" \
      -u "$TZP_KEY:$TZP_SECRET"
    ```

    ```json Response (trimmed) theme={null}
    {
      "capabilities": [
        {
          "payment_method_type": "local_bank_transfer_sgd",
          "currencies": [
            "SGD"
          ],
          "transfer_limit": {
            "minimum": {
              "amount": 100,
              "ccy": "SGD"
            },
            "maximum": {
              "amount": 100000000,
              "ccy": "SGD"
            },
            "currency": "SGD"
          },
          "local": {
            "fund_transfer_networks": [
              {
                "name": "FAST",
                "additional_information": "Near-instant, 24x7."
              },
              {
                "name": "PayNow",
                "additional_information": "Near-instant, 24x7."
              },
              {
                "name": "MEPS",
                "additional_information": "Same-day on business days."
              }
            ]
          },
          "on_behalf_of": {
            "support": true,
            "additional_requirements": [
              "entity_submission_required"
            ]
          },
          "setup_time": "instant",
          "account_reenablement_supported": true
        }
      ]
    }
    ```

    <Note>
      Sandbox availability may differ from production. In production, what you can provision depends on your onboarding profile — if a corridor you need is missing here, check [Virtual Account coverage](/collection-accounts/coverage/virtual-accounts) and talk to your account manager.
    </Note>

    Full reference: [Virtual Account Metadata](/api-reference/tazapay-api/virtual-account-metadata). For stablecoins, call [Wallet Metadata](/api-reference/tazapay-api/wallet-metadata) instead.
  </Step>

  <Step title="Create the collection account">
    Create a Singapore SGD Virtual Account on the local rail. Only `type` and `payment_method_type` are required by the schema; `country` and `currencies` are additionally required for virtual accounts.

    ```bash Request theme={null}
    curl -X POST "$TZP_BASE/v3/collection_account" \
      -u "$TZP_KEY:$TZP_SECRET" \
      -H "Content-Type: application/json" \
      -d '{
        "type": "virtual_account",
        "payment_method_type": "local_bank_transfer_sgd",
        "country": "SG",
        "currencies": ["SGD"],
        "alias": "quickstart-account",
        "description": "Quickstart test account for SGD collections"
      }'
    ```

    ```json Response theme={null}
    {
      "id": "cva_d2dgk0552psfuj1he0",
      "object": "collection_account",
      "type": "virtual_account",
      "payment_method_type": "local_bank_transfer_sgd",
      "country": "SG",
      "currencies": [
        "SGD"
      ],
      "status": "disabled",
      "alias": "quickstart-account",
      "description": "Quickstart test account for SGD collections",
      "requests": [
        {
          "id": "req_cva001enablement",
          "object": "collection_account_request",
          "collection_account_id": "cva_d2dgk0552psfuj1he0",
          "type": "enablement",
          "status": "processing",
          "requested_currencies": [
            "SGD"
          ],
          "created_at": "2024-09-26T09:39:25.03501Z",
          "updated_at": "2024-09-26T09:39:25.03501Z",
          "status_description": "Activation in progress."
        }
      ],
      "status_description": "",
      "metadata": {},
      "created_at": "2024-09-26T09:39:25.03501Z",
      "updated_at": "2024-09-26T09:39:25.03501Z"
    }
    ```

    Note the account is born `disabled` with an `enablement` request attached — it cannot receive funds yet. The account's `status` is derived from the state of that request, not set directly. For the full request lifecycle and every state a request can pass through, see [Collection Account Status Flow](/collection-accounts/requesting-for-vas/api#collection-account-status-flow).

    Save the returned `id` — every step below uses it:

    ```bash theme={null}
    export CVA_ID="cva_d2dgk0552psfuj1he0"
    ```
  </Step>

  <Step title="Wait for enablement">
    <Tabs>
      <Tab title="Webhooks (recommended)">
        Subscribe to `collection_account.creation_succeeded`. It fires when the enablement request succeeds and the account flips to `enabled`.

        ```json collection_account.creation_succeeded (trimmed) theme={null}
        {
          "type": "collection_account.creation_succeeded",
          "id": "evt_crqinqs584jmicmfjbhg",
          "object": "event",
          "created_at": "2024-09-26T09:39:55.369534811Z",
          "data": {
            "id": "cva_d2dgk0552psfuj1he0",
            "object": "collection_account",
            "payment_method_type": "local_bank_transfer_sgd",
            "status": "enabled",
            "currencies": [
              "SGD"
            ],
            "virtual_account": {
              "account_holder_name": "OM Grand Limited",
              "account_number": "0109866363",
              "bank_name": "STANDARD BANK LIMITED",
              "bank_codes": {
                "swift_code": "SLSGO2XXX"
              }
            },
            "created_at": "2024-09-26T09:39:25.03501Z",
            "updated_at": "2024-09-26T09:39:25.03501Z"
          }
        }
        ```

        The same family of events reports the unhappy paths — `creation_requires_action`, `creation_under_approval_hold`, `creation_failed`, `creation_cancelled`. Handle at least `creation_failed` before going live. Full list and payloads: [Collection Account Webhooks](/api-reference/tazapay-api/collection-account-webhooks).

        On setting up and securing your endpoint, see the [Webhooks Guide](/api-reference/appendix/webhooks-guide) and [Webhook Authentication](/api-reference/appendix/webhook-authentication).
      </Tab>

      <Tab title="Polling">
        Poll the account until `status` is `enabled`.

        ```bash Request theme={null}
        curl -X GET "$TZP_BASE/v3/collection_account/$CVA_ID" \
          -u "$TZP_KEY:$TZP_SECRET"
        ```

        Once enablement succeeds, the account looks like this — `status: enabled`, and the `enablement` request in `requests` now reads `succeeded`:

        ```json expandable Collection Account — enabled SGD virtual account theme={null}
        {
          "id": "cva_d2dgk0552psfuj1he0",
          "object": "collection_account",
          "type": "virtual_account",
          "payment_method_type": "local_bank_transfer_sgd",
          "country": "SG",
          "currencies": [
            "SGD"
          ],
          "status": "enabled",
          "alias": "quickstart-account",
          "description": "This account is used for SGD collections",
          "virtual_account": {
            "account_holder_name": "OM Grand Limited",
            "account_number": "0109866363",
            "iban": "",
            "bank_name": "STANDARD BANK LIMITED",
            "bank_branch": "8 MARINA BOULEVARD, 27-01, MARINA BAY FINANCIAL CENTRE",
            "bank_address": {
              "address_line_1": "",
              "address_line_2": "",
              "city": "",
              "country": "Singapore"
            },
            "bank_codes": {
              "swift_code": "SLSGO2XXX"
            },
            "account_reenablement_supported": true
          },
          "requests": [
            {
              "id": "req_cva001enablement",
              "object": "collection_account_request",
              "collection_account_id": "cva_d2dgk0552psfuj1he0",
              "type": "enablement",
              "status": "succeeded",
              "requested_currencies": [
                "SGD"
              ],
              "created_at": "2024-09-26T09:39:25.03501Z",
              "updated_at": "2024-09-26T09:39:30.03501Z",
              "status_description": "Account enabled successfully."
            }
          ],
          "status_description": "",
          "metadata": {},
          "created_at": "2024-09-26T09:39:25.03501Z",
          "updated_at": "2024-09-26T09:41:43.349835Z"
        }
        ```

        Field-level reference: [Collection Account object](/api-reference/tazapay-api/global-collection-account-object).
      </Tab>
    </Tabs>
  </Step>

  <Step title="Fetch the account details your payer needs">
    Fetch the account and read the `virtual_account` block. These are the coordinates your payer transfers to.

    ```bash Request theme={null}
    curl -X GET "$TZP_BASE/v3/collection_account/$CVA_ID" \
      -u "$TZP_KEY:$TZP_SECRET"
    ```

    ```json Virtual account details to share with your payer theme={null}
    {
      "id": "cva_d2dgk0552psfuj1he0",
      "object": "collection_account",
      "status": "enabled",
      "country": "SG",
      "currencies": [
        "SGD"
      ],
      "payment_method_type": "local_bank_transfer_sgd",
      "virtual_account": {
        "account_holder_name": "OM Grand Limited",
        "account_number": "0109866363",
        "iban": "",
        "bank_name": "STANDARD BANK LIMITED",
        "bank_branch": "8 MARINA BOULEVARD, 27-01, MARINA BAY FINANCIAL CENTRE",
        "bank_address": {
          "address_line_1": "",
          "address_line_2": "",
          "city": "",
          "country": "Singapore"
        },
        "bank_codes": {
          "swift_code": "SLSGO2XXX"
        }
      }
    }
    ```

    The keys present under `bank_codes` vary by country and rail — it may contain `swift_code`, `routing_code`, `sort_code`, `ach_routing_number`, `fedwire_routing_number`, `bsb_code`, or `bank_code`. Read them dynamically rather than assuming a fixed set. Full reference: [Collection Account object](/api-reference/tazapay-api/global-collection-account-object).

    In production, these are the details you display to your customer or print on your invoice. The payer then makes a normal domestic transfer to this account — from their side it looks like paying a local business, not an international wire.
  </Step>

  <Step title="Simulate an incoming payment">
    Sandbox includes a **Collect Simulation** feature so you can mimic an incoming payment without moving real money. This step is performed from the dashboard, not the API.

    Go to the [Sandbox dashboard](https://dashboard-sandbox.tazapay.com/) → **Virtual Accounts/Wallets** → **Simulate Collect**, pick the account you just created, and simulate the `succeeded` state.

    You can simulate every intermediate and terminal state, which is how you exercise the unhappy paths in your integration:

    | State flow              | What it exercises                                    |
    | ----------------------- | ---------------------------------------------------- |
    | `succeeded`             | The happy path — collect settled successfully        |
    | `on_hold` → `succeeded` | Held for compliance review, then cleared and settled |
    | `on_hold` → `failed`    | Held for review and rejected — compliance failure    |
    | `failed`                | Collect rejected outright                            |

    Stablecoin wallets add `detected` transitions, since on-chain payments are visible before final confirmation. The complete matrix for both fiat and crypto is on [Simulating Collects on Sandbox](/api-reference/tazapay-api/simulate-collects-on-sandbox).

    <Note>
      Simulated collects also create a real sandbox balance, which you can then use to fund and test payouts end to end.
    </Note>
  </Step>

  <Step title="Receive the collect and confirm the credit">
    **The webhook.** As soon as the collect settles, `collect.succeeded` fires. This is the event your system should treat as the signal that money arrived — note `balance_transaction`, which ties the collect to the ledger entry on your balance.

    ```json expandable collect.succeeded theme={null}
    {
      "type": "collect.succeeded",
      "id": "evt_d30mfcg3obm733raoh7g",
      "object": "event",
      "created_at": "2025-09-10T11:57:38.761234462Z",
      "data": {
        "id": "col_d30mfargpkanp3hrmqhg",
        "object": "collect",
        "amount": 100000,
        "currency": "SGD",
        "status": "succeeded",
        "type": "local_bank_transfer_sgd",
        "payer_details": {
          "name": "John Doe",
          "payer_bank": {
            "account_number": "",
            "name": "",
            "address": null,
            "bank_codes": {
              "swift_code": "sdasd93e"
            }
          },
          "reference_id": "",
          "additional_information": ""
        },
        "destination": "cva_d2dgk0552psfuj1he0",
        "destination_details": {
          "type": "virtual_account",
          "virtual_account": {
            "id": "cva_d2dgk0552psfuj1he0",
            "object": "virtual_account",
            "account_holder_name": "OM Grand Limited",
            "account_number": "0109866363",
            "bank_name": "STANDARD BANK LIMITED",
            "bank_branch": "8 MARINA BOULEVARD, 27-01, MARINA BAY FINANCIAL CENTRE",
            "bank_address": {
              "address_line_1": "",
              "address_line_2": "",
              "city": "",
              "country": "Singapore",
              "postal_code": "",
              "state": ""
            },
            "bank_codes": {
              "swift_code": "SLSGO2XXX"
            },
            "currencies": [
              "SGD"
            ],
            "iban": ""
          }
        },
        "holding_currency": "SGD",
        "balance_transaction": "btr_d30mfcjgpkanp3hrmql0",
        "on_behalf_of": "",
        "metadata": {},
        "created_at": "2025-09-10T11:57:31.967513Z",
        "tracking_details": null
      }
    }
    ```

    All collect events and their payloads: [Collect Webhooks](/api-reference/tazapay-api/collect-webhook).

    The sibling events are `collect.failed`, `collect.on_hold`, and `collect.detected` (wallets only). See [Collect Webhooks](/collection-accounts/incoming-payments/webhooks).

    **Fetch the collect.** Take the collect ID from the webhook and fetch it directly:

    ```bash Request theme={null}
    curl -X GET "$TZP_BASE/v3/collect/col_d30mfargpkanp3hrmqhg" \
      -u "$TZP_KEY:$TZP_SECRET"
    ```

    ```json expandable Collect — succeeded USD collect theme={null}
    {
      "status": "success",
      "message": "",
      "data": {
        "id": "col_d2fapsh76og2qj0ej5g",
        "object": "collect",
        "amount": 100000,
        "currency": "USD",
        "holding_currency": "USD",
        "status": "succeeded",
        "type": "wire_transfer",
        "destination": "cva_d2dgk0552psfuj1he0",
        "destination_details": {
          "type": "virtual_account",
          "virtual_account": {
            "id": "cva_d2dgk0552psfuj1he0",
            "object": "virtual_account",
            "account_holder_name": "OM Grand Limited",
            "account_number": "0109866363",
            "bank_name": "STANDARD BANK LIMITED",
            "bank_branch": "8 MARINA BOULEVARD, 27-01, MARINA BAY FINANCIAL CENTRE",
            "bank_address": {
              "address_line_1": "",
              "address_line_2": "",
              "city": "",
              "country": "Singapore",
              "postal_code": "",
              "state": ""
            },
            "bank_codes": {
              "swift_code": "SLSGO2XXX"
            },
            "currencies": [
              "USD"
            ],
            "iban": ""
          }
        },
        "payer_details": {
          "name": "CMC COMPANY",
          "payer_bank": {
            "account_number": "1112019837840",
            "name": "C Bank",
            "address": null,
            "bank_codes": {
              "swift_code": "AJUM7CHBKXXX"
            }
          },
          "reference_id": "",
          "additional_information": "CM Payment for Order 56"
        },
        "balance_transaction": "btr_u7ftrgipu69og2qj1j1pg",
        "on_behalf_of": "",
        "metadata": {},
        "tracking_details": null,
        "created_at": "2025-08-15T03:43:46.980214Z"
      }
    }
    ```

    Field-level reference: [Collect object](/api-reference/tazapay-api/collects). Amounts are in the currency's smallest unit — `100000` here is USD 1,000.00.

    The four fields to reconcile against are `status` (`succeeded`), `amount` and `currency` (what arrived), `destination` (which collection account received it), and `balance_transaction` (the ledger entry).

    **Confirm the balance.** Finally, check that the funds are on your balance:

    ```bash Request theme={null}
    curl -X GET "$TZP_BASE/v3/balance" \
      -u "$TZP_KEY:$TZP_SECRET"
    ```

    ```json Response (trimmed) theme={null}
    {
      "status": "success",
      "message": "",
      "data": {
        "available": [
          {
            "amount": "100000",
            "currency": "SGD"
          }
        ],
        "object": "balance",
        "updated_at": "2024-08-20T06:18:11.475605Z"
      }
    }
    ```

    Balance amounts are strings in the currency's smallest unit — `"100000"` is SGD 1,000.00.

    If the incoming currency is not one of your holding currencies, it is converted automatically at the point of credit rather than as a separate step — see [FX](/collection-accounts/incoming-payments/fx).
  </Step>
</Steps>

***

## Going to production

* **Handle compliance holds** — subscribe to `collect.on_hold` and surface held payments rather than treating silence as failure → [Compliance Holds](/collection-accounts/incoming-payments/compliance-holds)
* **Understand the full collect state machine**, including the wallet-only `detected` state → [State Machine](/collection-accounts/incoming-payments/state-machine)
* **Plan for reversals** when a collect fails after funds have arrived → [Reversals](/collection-accounts/incoming-payments/reversals)
* **Decide your holding currencies** and how FX should behave → [FX](/collection-accounts/incoming-payments/fx) and [Enabling Additional Balance Currencies](/getting-started/core-concepts/enabling-additional-balance-currencies)
* **Review coverage** for the corridors you actually need → [Virtual Accounts](/collection-accounts/coverage/virtual-accounts) and [Stablecoins](/collection-accounts/coverage/stablecoins)
* **Collecting for your customers?** Read [Collections on Behalf Of](/collection-accounts/integration-guides/collections-on-behalf-of) for entity-level attribution
* **Read the use case guide** matching your business → [B2B Collections](/collection-accounts/use-case-guides/b2b-collections), [Financial Institutions](/collection-accounts/use-case-guides/financial-institutions), or [Marketplaces](/collection-accounts/use-case-guides/marketplaces)

***

<CardGroup cols={2}>
  <Card title="Request via Dashboard" icon="table-columns" href="/collection-accounts/requesting-for-vas/dashboard">
    Prefer no code? Provision the same account from the Tazapay dashboard.
  </Card>

  <Card title="Collection Account API Reference" icon="code" href="/api-reference/tazapay-api/create-collection-account">
    Every field, enum, and endpoint for collection accounts.
  </Card>
</CardGroup>
