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

# Quickstart

> Create and track your first sandbox payout with Python

Create a sandbox payout from your trading account to your own bank account, then track its status. This is a withdrawal; the API uses the same [payout object](/fx/api-reference/payouts/create-payout) for withdrawals and virtual-account payouts.

## Before you start

You need three things from Hop, issued together when your organization's KYC is approved:

| Credential or ID | Example | Used for |
| - | - | - |
| API key and secret | Issued by Hop | Signing every request. See [Authentication](/fx/api-reference/authentication). |
| Customer id | `cus_4b1d8e3f7a6c2d9e5f0a1b3c` | The `{customer_id}` path segment: your organization |
| Account id | `acct_9f2a7c1e6a2b4f3c9b8d2e5a` | The `{account_id}` path segment: the account whose money moves. See [Accounts](/fx/guides/core-concepts#how-the-pieces-relate) |

You also need:

* `read` access on `accounts`, and `write` access on `payments` and `webhooks`.
* A sandbox trading account with enough USD for the `100.00` payout and any fees. Use [Simulate Payin](/fx/api-reference/payin-simulations/simulate-payin) to fund it.
* A running HTTPS webhook receiver that can [verify Hop's signature](/fx/webhooks/security).
* Python 3 with `httpx` installed.

## Set up the client

Run the following examples in order in the same Python session or script. Replace the four credential and ID placeholders below. This helper signs and sends each request; [Authentication](/fx/api-reference/authentication#building-a-signed-request) explains the signing scheme and includes JavaScript and cURL examples.

```bash theme={null}
python -m pip install httpx
```

```python Python theme={null}
import hashlib, hmac, json, time, uuid
import httpx

API_KEY = "<your api key>"
API_SECRET = "<your api secret>"
CUSTOMER_ID = "<your customer id>"  # cus_...
ACCOUNT_ID = "<your account id>"  # acct_...
BASE_URL = "https://api.sbx.hopnow.io"

def call(method, path_and_query, body_obj=None, extra_headers=None):
    body = json.dumps(body_obj, separators=(",", ":")) if body_obj is not None else ""
    timestamp = str(int(time.time()))
    nonce = str(uuid.uuid4())
    payload = f"{method.upper()}{path_and_query}{timestamp}{nonce}{body}"
    signature = hmac.new(API_SECRET.encode(), payload.encode(), hashlib.sha256).hexdigest()
    headers = {
        "X-API-Key": API_KEY,
        "X-Timestamp": timestamp,
        "X-Nonce": nonce,
        "X-Signature": signature,
        "Content-Type": "application/json",
        **(extra_headers or {}),
    }
    response = httpx.request(method, BASE_URL + path_and_query, content=body or None, headers=headers)
    response.raise_for_status()
    return response.json()
```

## 1. Check the funding balance

[Get Balances](/fx/api-reference/accounts/get-balances) returns the available funds in your trading account.

```python Python theme={null}
balances = call("GET", f"/v1/customers/{CUSTOMER_ID}/accounts/{ACCOUNT_ID}/balances")
print(balances["balances"])
```

Check that the available USD balance covers the payout and any fees before continuing.

## 2. Create a beneficiary

A [beneficiary](/fx/api-reference/beneficiaries/create-beneficiary) is who you are paying. Use `self_owned: True` for this withdrawal: funds from the trading account can only go to an account you own. The example uses a fictional individual and bank account for sandbox testing.

```python Python theme={null}
beneficiary = call("POST", f"/v1/accounts/{ACCOUNT_ID}/beneficiaries", {
    "beneficiary_type": "individual",
    "first_name": "John",
    "last_name": "Doe",
    "display_name": "John Doe",
    "address": {
        "address_line": "123 Main St",
        "city": "New York",
        "region": "NY",
        "postal_code": "10001",
        "country": "US",
    },
    "country_code": "US",
    "self_owned": True,
})
BENEFICIARY_ID = beneficiary["id"]  # bene_...
```

## 3. Add a payout destination

A [payout destination](/fx/api-reference/payout-destinations/create-destination) is the bank account or wallet under that beneficiary. This example adds a USD bank account; bank destinations are `active` immediately.

```python Python theme={null}
destination = call(
    "POST",
    f"/v1/accounts/{ACCOUNT_ID}/beneficiaries/{BENEFICIARY_ID}/payout-destinations",
    {
        "country": "US",
        "type": "bank_account",
        "currency": "USD",
        "account_name": "John Doe",
        "account_number": "1234567890",
        "account_type": "checking",
        "routing_number": "021000021",
        "bank_name": "Example Bank",
    },
)
DESTINATION_ID = destination["id"]  # dest_...
```

## 4. Register a webhook endpoint

[Register for completion and failure events](/fx/api-reference/webhooks/create-endpoint) before creating the payout. Replace the example URL with your running HTTPS receiver:

```python Python theme={null}
endpoint = call("POST", f"/v1/customers/{CUSTOMER_ID}/webhook-endpoints", {
    "url": "https://example.com/hooks/hop",
    "events": ["payout.completed", "payout.failed"],
})
WEBHOOK_SECRET = endpoint["secret"]  # returned once, on create
```

Store `secret` before you discard the response; it is not returned again. Configure your receiver to verify deliveries as described in [Webhook security](/fx/webhooks/security) before continuing. Events emitted before the endpoint is registered are not delivered to it later.

## 5. Create the payout

[Create Payout](/fx/api-reference/payouts/create-payout) uses the beneficiary and destination IDs returned above. Keep the same `Idempotency-Key` if you retry this request; see [Idempotency](/fx/api-reference/idempotency).

```python Python theme={null}
import uuid

idempotency_key = str(uuid.uuid4())

payout = call("POST", f"/v1/accounts/{ACCOUNT_ID}/payouts", {
    "beneficiary_id": BENEFICIARY_ID,
    "payout_destination_id": DESTINATION_ID,
    "amount": "100.00",
    "currency": "USD",
    "funding_source": {"type": "trading_account"},
    "note": "Quickstart payout",
}, extra_headers={"Idempotency-Key": idempotency_key})

PAYOUT_ID = payout["id"]  # po_...
print(PAYOUT_ID, payout["status"])  # pending
```

A `pending` payout is funded and queued; the money has not left yet.

## 6. Track the payout

Your endpoint receives `payout.completed` when the payout completes, or `payout.failed` if it fails or is cancelled before release. You can also poll its status:

```python Python theme={null}
payout = call("GET", f"/v1/accounts/{ACCOUNT_ID}/payouts/{PAYOUT_ID}")
print(payout["status"])
```

A successful payout moves `pending` → `processing` → `completed`. Match the webhook's `data.id` to `PAYOUT_ID` to reconcile it with your request. For retries and failed requests, see [Failure and recovery](/fx/flows/flow-6-failure-and-recovery).
