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

# Quickstart

> Begin with a guide on the fastest path to a successful outcome

This walks through the most common integration: giving a customer a dedicated virtual account number, then getting notified the moment they pay into it.

<Steps>
  <Step title="Get your API keys">
    Grab your `X-Api-Key` and `X-Api-Secret` from the **API Keys** page in your merchant dashboard. See [Authentication](/authentication) for how they're used.
  </Step>

  <Step title="Set your webhook URL">
    Go to **Webhook Settings** in your dashboard and set the URL we should call when a payment comes in, plus note your webhook secret — you'll use it to verify signatures. See [Webhooks](/api-reference/webhooks) for the full payload and verification example.
  </Step>

  <Step title="Create a virtual account">
    Pick a `reference` yourself — your own order ID or customer ID. You'll use it (not our internal ID) to look this transaction up later.

    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST "https://www.abcmpay.com/api/v1/virtual-account/create" \
        -H "X-Api-Key: your-public-key" \
        -H "X-Api-Secret: your-secret-key" \
        -H "Content-Type: application/json" \
        -d '{
          "customer_type": "individual",
          "first_name": "John",
          "last_name": "Doe",
          "email": "john@example.com",
          "reference": "ORDER_20260215120000",
          "bank": "palmpay"
      }'
      ```

      ```php PHP theme={null}
      <?php
      $curl = curl_init();
      curl_setopt_array($curl, [
          CURLOPT_URL => "https://www.abcmpay.com/api/v1/virtual-account/create",
          CURLOPT_RETURNTRANSFER => true,
          CURLOPT_POST => true,
          CURLOPT_HTTPHEADER => [
              "X-Api-Key: your-public-key",
              "X-Api-Secret: your-secret-key",
              "Content-Type: application/json",
          ],
          CURLOPT_POSTFIELDS => json_encode([
              "customer_type" => "individual",
              "first_name" => "John",
              "last_name" => "Doe",
              "email" => "john@example.com",
              "reference" => "ORDER_" . time(),
              "bank" => "palmpay",
          ]),
      ]);
      $response = curl_exec($curl);
      $data = json_decode($response, true);
      echo $data['data']['account_number'];
      ```
    </CodeGroup>

    The response includes a dedicated account number your customer can transfer into:

    ```json theme={null}
    {
        "success": true,
        "message": "Virtual account created successfully",
        "data": {
            "account_number": "0123456789",
            "account_name": "Your Business - John Doe",
            "bank_name": "PalmPay",
            "reference": "ORDER_20260215120000",
            "status": "Enabled"
        }
    }
    ```
  </Step>

  <Step title="Show the customer the account number">
    Display `account_number` and `bank_name` to your customer, or the returned details however fits your flow. Any amount they send lands in your wallet.
  </Step>

  <Step title="Get notified when they pay">
    We POST to your webhook URL the moment the transfer clears — no polling required. Verify the `X-Webhook-Signature` header before trusting the payload; the full example is in [Webhooks](/api-reference/webhooks#verifying-the-signature).

    ```json theme={null}
    {
        "event": "payment.received",
        "nonce": "9f2a7c1e4b0d8a3f6c5e9b1d2a4f7c0e",
        "sent_at": "2026-05-10T15:25:13Z",
        "data": {
            "reference": "Transfer from JOHN DOE",
            "amount": 10000,
            "currency": "NGN",
            "virtual_account": "0123456789",
            "payer_name": "John Doe",
            "payer_bank": "ACCESS BANK",
            "transaction_id": "MI2053495351264129024",
            "status": "successful"
        }
    }
    ```

    For a virtual account payment like this one, `reference` is actually the payer's bank transfer narration — not something you or we generate, and not guaranteed unique. `transaction_id` is ABCMPay's own internal ID for the transaction, always unique — use that (not `reference`) to match the webhook back to your own records. See [why the two are different](/authentication#reference-vs-transaction-id) for the full breakdown by endpoint.
  </Step>
</Steps>

## Where to next

<CardGroup cols={2}>
  <Card title="Virtual Accounts" icon="building-columns" href="/api-reference/virtual-accounts">
    Full endpoint reference: create, fetch, list.
  </Card>

  <Card title="Collect Payments" icon="link" href="/api-reference/checkout">
    Prefer a one-time payment link instead of a dedicated account? Start here.
  </Card>

  <Card title="Payouts" icon="money-bill-transfer" href="/api-reference/payouts">
    Send money back out to a bank account.
  </Card>

  <Card title="Webhooks" icon="webhook" href="/api-reference/webhooks">
    Full payload reference, signature verification, and replay protection.
  </Card>
</CardGroup>
