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

# Collect with PHP

> Collect a payment via invoice (orders use the same flow) using the Dollr API from PHP.

<Note>
  **Invoices vs orders:** These guides walk through **invoices** (formal billing, line items, publish). The collect flow is the same for **orders** — use `/v1/orders/*` instead of `/v1/invoices/*` and set `source_type: "ORDER"` on the checkout session. See [Orders](/api/orders) and [Parties & counterparties](/concepts/parties-and-counterparties).

  **Hosted checkout:** To skip party, invoice, session, and execute steps entirely, see [Hosted checkout](/guides/hosted-checkout).
</Note>

End-to-end **invoice collection** with PHP 8.1+ and cURL (or Guzzle). See [Quick Start](/quickstart) for the full multi-language tutorial.

<Note>
  **API Reference:** [Obtain token](/api-reference/jwt/client-obtain-token) · [Collect](/api-reference/executions/collect)
</Note>

## Prerequisites

* PHP 8.1+ with `curl` extension (or `guzzlehttp/guzzle`)
* API credentials in environment variables — **server-side only**

## Steps

<Steps>
  <Step title="Get an access token">
    ```php theme={null}
    $baseUrl = 'https://api.heydollr.app';

    $ch = curl_init("$baseUrl/v1/jwt/client/obtain/token");
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST           => true,
        CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
        CURLOPT_POSTFIELDS     => json_encode([
            'client_id'     => getenv('DOLLR_CLIENT_ID'),
            'client_secret' => getenv('DOLLR_CLIENT_SECRET'),
        ]),
    ]);
    $token = json_decode(curl_exec($ch), true)['access_token'];
    curl_close($ch);

    $headers = [
        'Authorization: Bearer ' . $token,
        'Content-Type: application/json',
    ];
    ```
  </Step>

  <Step title="Party, counterparty, invoice">
    ```php theme={null}
    function dollrPost(string $url, array $body, array $headers): array {
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST           => true,
            CURLOPT_HTTPHEADER     => $headers,
            CURLOPT_POSTFIELDS     => json_encode($body),
        ]);
        $out = json_decode(curl_exec($ch), true);
        curl_close($ch);
        return $out;
    }

    $party = dollrPost("$baseUrl/v1/parties/create", [
        'fullname' => 'Amara Kamara', 'phone' => '231771234567',
        'email' => 'amara@example.com', 'country_code' => 'LR',
    ], $headers);

    $cp = dollrPost("$baseUrl/v1/counterparties/create", [
        'relationship_type' => 'CUSTOMER', 'party_id' => $party['id'],
    ], $headers);

    $invoice = dollrPost("$baseUrl/v1/invoices/create", [
        'counterparty_id' => $cp['id'], 'currency' => 'USD',
        'note' => 'Consulting', 'fee_bearer' => 'PAYER', 'as_payment_link' => true,
    ], $headers);
    ```
  </Step>

  <Step title="Publish, session, execute">
    ```php theme={null}
    $invoiceId = $invoice['id'];
    dollrPost("$baseUrl/v1/invoices/$invoiceId/items/add", [
        'name' => 'Strategy Session', 'currency' => 'USD', 'qty' => 1, 'amount' => 250.0,
    ], $headers);

    // PUT publish — use curl_setopt CURLOPT_CUSTOMREQUEST => 'PUT'
    $referenceId = bin2hex(random_bytes(16)); // use ramsey/uuid or uuid4() in production

    $session = dollrPost("$baseUrl/v1/sessions/checkout", [
        'source_id' => $invoiceId, 'source_type' => 'INVOICE',
    ], $headers);

    $execution = dollrPost("$baseUrl/v1/executions/collection", [
        'session_id'         => (string) $session['id'],
        'payment_account_id' => 'YOUR_PAYMENT_ACCOUNT_ID',
        'currency'           => 'USD',
        'reference_id'       => $referenceId,
    ], $headers);
    ```

    Register a [payment account](/api/payment-accounts) before execute. Store `$referenceId` before the HTTP call.
  </Step>

  <Step title="Poll status">
    ```php theme={null}
    $ch = curl_init("$baseUrl/v1/status/collection/$referenceId");
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    $status = json_decode(curl_exec($ch), true);
    curl_close($ch);
    ```
  </Step>
</Steps>

## Try it yourself

<CardGroup cols={3}>
  <Card title="Hosted checkout" icon="window-maximize" href="/guides/hosted-checkout">
    Mobile money and card on a Dollr-hosted page — fastest path.
  </Card>

  <Card title="Orders" icon="box" href="/api/orders">
    Same collect flow with `source_type: ORDER` and `/v1/orders/*`.
  </Card>

  <Card title="Direct checkout" icon="cart-shopping" href="/guides/collect-via-checkout">
    One API call to create source — API-embedded flow.
  </Card>
</CardGroup>

## Related

* [Hosted checkout](/guides/hosted-checkout) · [Orders](/api/orders)
* [Collect via checkout](/guides/collect-via-checkout)
* [Choose your integration](/guides/choose-integration)
* [Error handling](/guides/error-handling)
* [Sessions & executions](/concepts/sessions-and-executions)
