Core design principles and integration patterns that apply across all Infinia APIs.
This page covers the patterns and conventions that apply across all Infinia APIs. Reading it before you start will save you time later.
Resources are async
All Infinia APIs are async-first. When you create a resource — a payment, a payout, an internal transfer — the API returns immediately with an initial state (typically PENDING or IN_PROGRESS). The final outcome arrives later via webhook.
Every resource follows the same lifecycle:
- Create —
POSTto the relevant endpoint. You get back the resource in its initial state. - Poll —
GETthe resource by ID if you need to check its current state on demand. - Webhook — Infinia
POSTs the updated resource to your callback URL when its state changes.
The object returned by the create endpoint, the get endpoint, and the webhook payload all share the same schema. You can reuse the same parsing and validation logic across all three.
Use webhooks, not polling
The right way to track state changes is webhooks. They're near-real-time, automatically retried on failure, and scale without any extra effort on your side.
Polling the retrieve endpoint is fine as a fallback — for example, to reconcile state after a webhook delivery failure or a temporary outage on your side — but it should not be your primary approach.
See the Webhooks page for setup instructions, signature verification, and retry behaviour.
Idempotency
Operations that move money — payouts, internal transfers, and similar — require a unique identifier in the request body (the field name varies by endpoint, e.g. origin_id, idempotency_key). This value acts as an idempotency key.
If you submit the same key twice, the API returns the result of the first request instead of executing the operation again. This makes it safe to retry after a timeout or a 5xx error without risking a duplicate transaction.
The recommended pattern:
- Generate a unique identifier for each operation and persist it on your side before sending the request
- If the request fails due to a network error or
5xx, retry with the same identifier - Do not retry on
4xxerrors — those indicate a problem with the request itself
Idempotency protects against duplicate execution, not against bad inputs. A request that fails with a
400will return the same400if retried with the same key.
Pagination
List endpoints use cursor-based pagination. Pass limit (max 100) to control page size, and pass the next_cursor from each response to fetch the next page. When has_more is false, you've reached the end.
Keep your filters consistent across all pages of a session — changing a filter mid-session will invalidate the cursor.
See the Pagination page for a full example.
Questions or feedback
If you run into something unexpected or have suggestions, reach out at [email protected].

