> ## 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.

# Quick Start

> Go from zero to a successful payment collection in under 10 minutes.

# Quick Start

> **Note:**
> **Try in API Reference:** [Obtain token](/api-reference/jwt/client-obtain-token) · [Create invoice](/api-reference/invoices/create-invoice) · [Collect](/api-reference/executions/collect) · [Collection status](/api-reference/status/get-collection-status)

Get from zero to your first successful payment collection in under 10 minutes.

This quick start shows the document-first (invoice/order) collection flow. The public API also supports creating a checkout source directly from payer details via the Checkouts API (`POST /v1/checkouts/create`). See API Reference → Checkouts for the direct checkout-source flow.

**Base URL:** `https://api.heydollr.app`

***

## Before You Begin

You need a verified Dollr merchant account with API credentials. If you haven't done this yet:

1. Register at [merchant.heydollr.app](https://merchant.heydollr.app)
2. Complete identity verification (1–72 hours)
3. Go to **Settings → Developer → API Keys** and generate a **Client ID** and **Client Secret**

***

## Step 1 — Get an Access Token

Exchange your credentials for a JWT Bearer token. Every API call requires this token in the `Authorization` header.

```http theme={null}
POST /v1/jwt/client/obtain/token
```

```bash theme={null}
curl -X POST "https://api.heydollr.app/v1/jwt/client/obtain/token" \
  -H "Content-Type: application/json" \
  -d '{
    "client_id":     "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET"
  }'
```

```python theme={null}
import requests

BASE_URL = "https://api.heydollr.app"

res = requests.post(f"{BASE_URL}/v1/jwt/client/obtain/token", json={
    "client_id":     "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET",
})
token = res.json()["access_token"]
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
```

```javascript theme={null}
const BASE_URL = "https://api.heydollr.app";

const { access_token } = await fetch(`${BASE_URL}/v1/jwt/client/obtain/token`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    client_id:     "YOUR_CLIENT_ID",
    client_secret: "YOUR_CLIENT_SECRET",
  }),
}).then(r => r.json());

const headers = {
  Authorization:  `Bearer ${access_token}`,
  "Content-Type": "application/json",
};
```

**Response:**

```json theme={null}
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expires_in": 60
}
```

> **Tip:**
> Tokens expire after `expires_in` **minutes**. Refresh proactively — request a new token when less than 5 minutes remain.

***

## Step 2 — Create a Party

A Party is a contact record for the person you're collecting from.

```http theme={null}
POST /v1/parties/create
```

```bash theme={null}
curl -X POST "https://api.heydollr.app/v1/parties/create" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "fullname":     "Amara Kamara",
    "phone":        "231771234567",
    "email":        "amara@example.com",
    "country_code": "LR"
  }'
```

```python theme={null}
party = requests.post(f"{BASE_URL}/v1/parties/create", headers=headers, json={
    "fullname":     "Amara Kamara",
    "phone":        "231771234567",
    "email":        "amara@example.com",
    "country_code": "LR",
}).json()

party_id = party["id"]
```

```javascript theme={null}
const party = await fetch(`${BASE_URL}/v1/parties/create`, {
  method: "POST", headers,
  body: JSON.stringify({
    fullname:     "Amara Kamara",
    phone:        "231771234567",
    email:        "amara@example.com",
    country_code: "LR",
  }),
}).then(r => r.json());

const partyId = party.id;
```

**Response:**

```json theme={null}
{
  "id": 42,
  "fullname": "Amara Kamara",
  "phone": "231771234567",
  "email": "amara@example.com",
  "country_code": "LR",
  "created_at": "2025-06-01T10:00:00Z",
  "updated_at": "2025-06-01T10:00:00Z"
}
```

***

## Step 3 — Create a Counterparty

Link the Party to your merchant account with a relationship type.

```http theme={null}
POST /v1/counterparties/create
```

```bash theme={null}
curl -X POST "https://api.heydollr.app/v1/counterparties/create" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"relationship_type": "CUSTOMER", "party_id": 42}'
```

```python theme={null}
cp = requests.post(f"{BASE_URL}/v1/counterparties/create", headers=headers, json={
    "relationship_type": "CUSTOMER",
    "party_id":          party_id,
}).json()

counterparty_id = cp["id"]
```

```javascript theme={null}
const cp = await fetch(`${BASE_URL}/v1/counterparties/create`, {
  method: "POST", headers,
  body: JSON.stringify({ relationship_type: "CUSTOMER", party_id: partyId }),
}).then(r => r.json());

const counterpartyId = cp.id;
```

> **Note:**
> This step is required for the direct invoice flow shown here. If you use the checkout-source shortcut (`POST /v1/checkouts/create`), Dollr can create or match the Party and Counterparty automatically from payer details.

***

## Step 4 — Create and Publish an Invoice

Create the invoice, add a line item, then publish it.

```http theme={null}
POST /v1/invoices/create
```

```bash theme={null}
# Create invoice
curl -X POST "https://api.heydollr.app/v1/invoices/create" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "counterparty_id": 15,
    "currency":        "USD",
    "note":            "Consulting services",
    "fee_bearer":      "PAYER",
    "as_payment_link": true
  }'

# Add a line item (replace 101 with your invoice id)
curl -X POST "https://api.heydollr.app/v1/invoices/101/items/add" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Strategy Session", "currency": "USD", "qty": 1, "amount": 250.00}'

# Publish (locks the invoice and activates it for payment)
curl -X PUT "https://api.heydollr.app/v1/invoices/publish/101" \
  -H "Authorization: Bearer $TOKEN"
```

```python theme={null}
# Create invoice
invoice = requests.post(f"{BASE_URL}/v1/invoices/create", headers=headers, json={
    "counterparty_id": counterparty_id,
    "currency":        "USD",
    "note":            "Consulting services",
    "fee_bearer":      "PAYER",
    "as_payment_link": True,
}).json()
invoice_id = invoice["id"]

# Add a line item
requests.post(f"{BASE_URL}/v1/invoices/{invoice_id}/items/add", headers=headers, json={
    "name":     "Strategy Session",
    "currency": "USD",
    "qty":      1,
    "amount":   250.00,
})

# Publish
invoice = requests.put(f"{BASE_URL}/v1/invoices/publish/{invoice_id}", headers=headers).json()
print("Status:", invoice["status"])  # ACTIVE
```

```javascript theme={null}
// Create invoice
const invoice = await fetch(`${BASE_URL}/v1/invoices/create`, {
  method: "POST", headers,
  body: JSON.stringify({
    counterparty_id: counterpartyId,
    currency:        "USD",
    note:            "Consulting services",
    fee_bearer:      "PAYER",
    as_payment_link: true,
  }),
}).then(r => r.json());
const invoiceId = invoice.id;

// Add a line item
await fetch(`${BASE_URL}/v1/invoices/${invoiceId}/items/add`, {
  method: "POST", headers,
  body: JSON.stringify({ name: "Strategy Session", currency: "USD", qty: 1, amount: 250.00 }),
});

// Publish
const published = await fetch(`${BASE_URL}/v1/invoices/publish/${invoiceId}`, {
  method: "PUT", headers,
}).then(r => r.json());
console.log("Status:", published.status); // ACTIVE
```

### Same flow with orders

For e-commerce or retail checkouts, swap invoice endpoints for orders and use `source_type: "ORDER"` in Step 5:

```bash theme={null}
curl -X POST "https://api.heydollr.app/v1/orders/create" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"counterparty_id": 15, "currency": "USD", "note": "Order #1042", "fee_bearer": "PAYER", "as_payment_link": true}'

# Add items → publish → checkout session with source_type ORDER
```

See [Orders](/api/orders). Stack guides under **Integrate by stack** use invoices as the default example; the steps are the same.

***

## Step 5 — Collect Payment

Create a checkout session, register the customer's wallet, then execute.

> **Warning:**
> **Generate your reference\_id before calling execute**

Store the UUID before the network call. You'll need it to query status if the response is lost.

```bash theme={null}
# Detect payment method from phone (optional but recommended)
curl "https://api.heydollr.app/v1/predictions/mmo-provider-info?phone=231771234567&operation_type=COLLECTION" \
  -H "Authorization: Bearer $TOKEN"

# Create checkout session
curl -X POST "https://api.heydollr.app/v1/sessions/checkout" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"source_id": 101, "source_type": "INVOICE"}'

# Register customer wallet (use method/provider from prediction)
curl -X POST "https://api.heydollr.app/v1/payment-accounts/create?operation_type=COLLECTION" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "account_name": "John Doe",
    "provider":     "MTN_MOMO_LBR",
    "method":       "MTN_MOMO_LBR",
    "party_id":     42,
    "country_code": "LR",
    "insensitive_account_number": "231771234567"
  }'

# Execute — store reference_id FIRST
REFERENCE_ID=$(python3 -c "import uuid; print(uuid.uuid4())")
curl -X POST "https://api.heydollr.app/v1/executions/collection" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{
    \"session_id\":         \"55\",
    \"payment_account_id\": \"18\",
    \"currency\":           \"USD\",
    \"reference_id\":       \"$REFERENCE_ID\"
  }"
```

```python theme={null}
from uuid import uuid4

# Detect payment method from phone
mmo = requests.get(f"{BASE_URL}/v1/predictions/mmo-provider-info", headers=headers, params={
    "phone": "231771234567", "operation_type": "COLLECTION",
}).json()
payment_method = mmo["payment_method"]
provider       = mmo["gateway_provider"]

# Create checkout session
session = requests.post(f"{BASE_URL}/v1/sessions/checkout", headers=headers, json={
    "source_id":   invoice_id,
    "source_type": "INVOICE",
}).json()
session_id = session["id"]

# Register customer wallet
account = requests.post(
    f"{BASE_URL}/v1/payment-accounts/create",
    headers=headers,
    params={"operation_type": "COLLECTION"},
    json={
        "account_name":               "Amara MTN Wallet",
        "provider":                   provider,
        "method":                     payment_method,
        "party_id":                   party_id,
        "country_code":               "LR",
        "insensitive_account_number": "231771234567",
    },
).json()

# Execute — generate and store reference_id BEFORE the call
reference_id = str(uuid4())
execution = requests.post(f"{BASE_URL}/v1/executions/collection", headers=headers, json={
    "session_id":         str(session_id),
    "payment_account_id": str(account["id"]),
    "currency":           "USD",
    "reference_id":       reference_id,
}).json()
print("Execution status:", execution["status"])
```

```javascript theme={null}
// Detect payment method from phone
const mmo = await fetch(
  `${BASE_URL}/v1/predictions/mmo-provider-info?phone=231771234567&operation_type=COLLECTION`,
  { headers: headers }
).then(r => r.json());

// Create checkout session
const session = await fetch(`${BASE_URL}/v1/sessions/checkout`, {
  method: "POST", headers,
  body: JSON.stringify({ source_id: invoiceId, source_type: "INVOICE" }),
}).then(r => r.json());

// Register customer wallet
const account = await fetch(
  `${BASE_URL}/v1/payment-accounts/create?operation_type=COLLECTION`,
  {
    method: "POST", headers,
    body: JSON.stringify({
      account_name:               "Amara MTN Wallet",
      provider:                   mmo.gateway_provider,
      method:                     mmo.payment_method,
      party_id:                   partyId,
      country_code:               "LR",
      insensitive_account_number: "231771234567",
    }),
  }
).then(r => r.json());

// Execute — generate and store reference_id BEFORE the call
const referenceId = crypto.randomUUID();
const execution = await fetch(`${BASE_URL}/v1/executions/collection`, {
  method: "POST", headers,
  body: JSON.stringify({
    session_id:         String(session.id),
    payment_account_id: String(account.id),
    currency:           "USD",
    reference_id:       referenceId,
  }),
}).then(r => r.json());
console.log("Execution status:", execution.status);
```

***

## Step 6 — Check Payment Status

```http theme={null}
GET /v1/status/collection/:reference_id
```

```bash theme={null}
curl "https://api.heydollr.app/v1/status/collection/$REFERENCE_ID" \
  -H "Authorization: Bearer $TOKEN"
```

```python theme={null}
status = requests.get(
    f"{BASE_URL}/v1/status/collection/{reference_id}",
    headers=headers,
).json()
print(status["status"])  # PENDING → PROCESSING → COMPLETED
```

```javascript theme={null}
const status = await fetch(`${BASE_URL}/v1/status/collection/${referenceId}`, { headers })
  .then(r => r.json());
console.log(status.status); // PENDING → PROCESSING → COMPLETED
```

**Status progression:** `PENDING` → `PROCESSING` → `COMPLETED` (or `FAILED`)

> **Note:**
> Mobile money payments may stay in `PROCESSING` for several minutes while the carrier confirms. Do not retry during this window — query status instead.

***

## Retrieve Receipt

After a successful collection (source status `PAID`), retrieve the receipt for the matching source family:

```http theme={null}
GET /v1/invoices/receipt/:id
GET /v1/orders/receipt/:id
```

Use the invoice or order system ID from your published source.

## What's Next

### Integrate by stack

* [Node.js](/guides/collect-with-nodejs) · [Python](/guides/collect-with-python) · [Django](/guides/collect-with-django) · [Ruby](/guides/collect-with-ruby) · [PHP](/guides/collect-with-php) · [Java](/guides/collect-with-java) · [Go](/guides/collect-with-go) · [Rust](/guides/collect-with-rust) · [.NET](/guides/collect-with-dotnet) · [Next.js](/guides/collect-with-nextjs) · [Laravel](/guides/collect-with-laravel)

### Payouts

* [Payout with Node.js](/guides/payout-with-nodejs)

### More guides

* [Collect via checkout](/guides/collect-via-checkout)
* [Integration guide](/guides/integration)
* [Realtime status](/guides/realtime-status)
* [API Reference — Collect](/api-reference/executions/collect)
* [Error catalog](/reference/error-catalog)
* [Knowledge Base](/knowledge-base)
