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

# Accept Payments with Invoices

> Create a crypto invoice, send your customer to the hosted payment page, and confirm the payment before you fulfil the order.

Invoices are the quickest way to accept a crypto payment for an order. You create an invoice with the price and the asset you accept, and Finrock gives you a deposit address and a hosted payment page. Your customer pays on that page, and you confirm the payment on your server before you fulfil the order.

This guide walks through the whole flow. For every field, see [Create Invoice](https://apidocs.finrock.io/api-reference/invoicing/create-invoice.md) and [List Invoices](https://apidocs.finrock.io/api-reference/invoicing/list-invoices.md).

> [!TIP]
>
> Want to embed a checkout form on your own page instead of sending customers to a hosted page? See [Payment Widget](https://apidocs.finrock.io/guides/payment-widget.md).

## How it works

1. Your server creates an invoice when the customer checks out.
2. You redirect the customer to the invoice's `payment_url`.
3. The customer sends the crypto to the invoice's deposit address before it expires.
4. Finrock notifies your `ipn_url`, and redirects the customer to your `success_url` or `failed_url`.
5. Your server confirms the invoice is `Paid`, then fulfils the order.

## Create an invoice

**1. Choose the asset and price**

Every invoice needs `crypto.asset_id`, the asset your customer pays in. Use the `id` value from [Supported Assets](https://apidocs.finrock.io/api-reference/utilities/supported-assets.md), for example `USDT_TRX` or `BTC`.

Then set the price in one of two ways:

* **In fiat:** send `fiat.asset_id` and `fiat.amount`, for example `USD` and `49.99`. Finrock converts it into the crypto amount due.
* **In crypto:** send `crypto.amount`, for example `0.001` BTC.

**2. Add a memo**

`memo` is required. Use your own order ID, such as `order-1042`, so you can match the invoice to the order and look it up later with [List Invoices](https://apidocs.finrock.io/api-reference/invoicing/list-invoices.md).

**3. Set your URLs**

* `ipn_url`: the URL on your server that receives payment notifications for this invoice only. It's separate from your account's webhook.
* `success_url`: where the customer goes after a successful payment.
* `failed_url`: where the customer goes if the payment fails.

**4. Send the request**

Call `POST /dac/v1/invoice` from your server. Never from a browser or mobile app, because the request is signed with your private key.

```bash cURL theme={null}
curl --request POST \
     --url https://api.finrock.io/dac/v1/invoice \
     --header 'Authorization: Bearer {JWT}' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'x-api-key: YOUR_API_KEY' \
     --data '{
       "fiat": {
         "asset_id": "USD",
         "amount": 49.99
       },
       "crypto": {
         "asset_id": "USDT_TRX"
       },
       "memo": "order-1042",
       "ipn_url": "https://example.com/webhooks/finrock",
       "success_url": "https://example.com/orders/1042/thanks",
       "failed_url": "https://example.com/orders/1042/payment-failed"
     }'
```

You can also pass `payer` details, such as name and email. See [Create Invoice](https://apidocs.finrock.io/api-reference/invoicing/create-invoice.md).

The response is the new invoice. Save its `id` against your order. The fields you'll use most:

| Field | What to do with it |
| - | - |
| `id` | Store it with your order to look the invoice up later. |
| `payment_url` | Redirect your customer here to pay. |
| `crypto.amount`, `crypto.address`, `crypto.address_tag` | The amount due and where to send it, if you show payment details yourself. Include `address_tag` on chains that use one, such as XRP. |
| `expiry_ts` | When the invoice expires, as a Unix timestamp in seconds. |
| `status` | `Pending` until a payment arrives. |

## Send the customer to pay

Redirect the customer to `payment_url`, where they see the amount due and the deposit address.

> [!NOTE]
>
> Invoices are time-limited. Payments received after `expiry_ts` may need manual reconciliation, so ask customers to pay before the invoice expires.

## Confirm the payment

Finrock sends a notification to the invoice's `ipn_url` each time the invoice's status changes, for example when it moves to `Processing` and again when it becomes `Paid`. This is separate from your account's [webhook](https://apidocs.finrock.io/guides/webhooks.md): each `ipn_url` only receives notifications for its own invoice, so you can set a different URL per invoice.

The notification body is the invoice object, in the same format as the [Create Invoice](https://apidocs.finrock.io/api-reference/invoicing/create-invoice.md#response) response but without the URL fields (`payment_url`, `ipn_url`, `success_url` and `failed_url`). Read its `id` and `status`.

Each notification is signed the same way as webhooks: verify the `x-signature` header against the raw request body with Finrock's public key before you trust it. See [Webhook Authentication](https://apidocs.finrock.io/guides/webhooks.md#webhook-authentication) for the key and a code example.

Once the signature checks out and `status` is `Paid`, fulfil the order. You can also look the invoice up with [List Invoices](https://apidocs.finrock.io/api-reference/invoicing/list-invoices.md) using its `id` to double-check.

```bash cURL theme={null}
curl --request GET \
     --url 'https://api.finrock.io/dac/v1/invoice?id=b198d0f8-dc7d-4418-a504-73aec3d2dc37' \
     --header 'Authorization: Bearer {JWT}' \
     --header 'accept: application/json' \
     --header 'x-api-key: YOUR_API_KEY'
```

> [!WARNING]
>
> Don't mark an order as paid just because the customer reached your `success_url`. Anyone can open that URL. Always confirm with a server-side check.

Because you get a notification for every status change, one invoice can notify your `ipn_url` several times. Fulfil the order only when the status is `Paid`, and make your handler idempotent so that fulfilling the same invoice twice has no effect.

Your `ipn_url` must return HTTP `200`. If it returns anything else, or doesn't respond in time, Finrock retries the notification with the same schedule as webhooks: up to 5 times, after 30, 60, 90, 120 and 180 seconds. See [Retry Policy](https://apidocs.finrock.io/guides/webhooks.md#retry-policy).

## Invoice statuses

| Status | What it means | What to do |
| - | - | - |
| `Pending` | Waiting for payment. | Wait. |
| `Processing` | The customer has paid, and Finrock is waiting for blockchain confirmations. Track progress in `confirmations`. | Wait for `Paid`. |
| `Paid` | The invoice is paid. | Fulfil the order. |
| `Expired` | The invoice expired before it was paid. | Create a new invoice if the customer still wants to pay. |
| `Failed` | The payment failed. | Let the customer try again with a new invoice. |
| `Cancelled` | The invoice was cancelled. | Don't fulfil the order. |
| `Refunded` | The payment was refunded. | Reverse the order if you fulfilled it. |

To see how much has been received so far, check `crypto.paid` and `crypto.pending`, or `fiat.paid` and `fiat.pending`. The payment's on-chain hash is in `txn_hash`, and its block confirmations are in `confirmations`, for example `3/5`.

## Find an invoice later

Use [List Invoices](https://apidocs.finrock.io/api-reference/invoicing/list-invoices.md) with:

* `id` for one invoice, or
* `memo` to find invoices by your own reference, such as your order ID.

If nothing matches, the API returns an empty array.

## Related

> [card] [Create Invoice](https://apidocs.finrock.io/api-reference/invoicing/create-invoice.md)
>
> Every request and response field.

> [card] [Webhooks](https://apidocs.finrock.io/guides/webhooks.md)
>
> Receive and verify payment events.

> [card] [Payment Widget](https://apidocs.finrock.io/guides/payment-widget.md)
>
> Embed a checkout form on your own site.

> [card] [Supported Assets](https://apidocs.finrock.io/api-reference/utilities/supported-assets.md)
>
> The asset IDs you can accept.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.