---
updatedAt: 2026-10-16T12:59:06.000Z
agentTools:
  projectIndex: https://docs.infiniaweb.com/llms.txt
---

# 📘 Developer Handbook

Learn the conventions that apply across every Infinia API: asynchronous operations, webhooks, idempotency and pagination.

Every Infinia API follows the same small set of conventions. Operations run asynchronously, webhooks tell you when they change, idempotency keys make retries safe, and list endpoints share one pagination model.

This page explains each convention and links to the page that covers it in detail. Reading it before you start saves time later.

## Operations are asynchronous

When you create an operation, such as a payin, a payout or an internal transfer, the API responds right away with the operation in its initial status, typically `PENDING`, `IN_PROGRESS` or `AWAITING`. The final outcome arrives later.

Every operation follows the same lifecycle:

1. **Create.** Send a `POST` to the operation's endpoint. The response holds the operation in its initial status.
2. **Retrieve.** Send a `GET` with the operation's ID whenever you need its current status.
3. **Get notified.** Infinia sends a `POST` with the updated operation to your callback URL each time its status changes.

<Callout icon="📘" theme="info">
  The create response, the retrieve response and the webhook body share the same schema. You can reuse the same parsing and validation code for all three.
</Callout>

## Track status changes with webhooks

Use webhooks as your main way to track status changes. They arrive in near real time, Infinia retries them when your endpoint is temporarily unavailable, and they scale without extra work on your side.

Polling the retrieve endpoint is a fallback, not your primary approach. Use it to reconcile state after a missed webhook or an outage on your side.

See [Webhooks](https://docs.infiniaweb.com/reference/getting-started-webhooks) for setup, signature verification and retry behavior.

## Make retries safe with idempotency keys

Operations that move money accept an identifier of your own in the request body, for example `originId` for payouts and `idempotency_key` for internal transfers and refunds. Infinia uses it as an idempotency key.

If you send a key that already exists, the API returns the operation that the first request created instead of creating a second one. This makes it safe to retry after a timeout or a `5xx` error.

To use idempotency keys:

1. Generate a unique key for each operation and save it on your side before you send the request.
2. If the request fails with a network error or a `5xx`, retry it with the **same key**.
3. Don't retry `4xx` errors. They mean the request itself has a problem.

<Callout icon="⚠️" theme="warning">
  Idempotency protects against duplicate execution, not against bad input. A request that fails with a `400` returns the same `400` when you retry it unchanged with the same key.
</Callout>

Payins don't deduplicate requests, and each resource names its key differently. See [Handling Failures](https://docs.infiniaweb.com/reference/handling-failures) for the key of each resource and how to look an operation up by it.

## Paginate list results

List endpoints use cursor-based pagination. Set the page size with `limit` (up to 100), and pass the `next_cursor` from each response as `cursor` to get the next page. When `has_more` is `false`, you've reached the end.

Send the same filters on every page. If a filter changes, the API rejects the cursor.

See [Pagination](https://docs.infiniaweb.com/reference/pagination) for a full example.

## Get help

If something behaves unexpectedly or you have suggestions, write to **<devs@infiniaweb.com>**.