API basics
This page covers the shared fundamentals that apply across all Latitude API products.
Base URL
All API requests are made to:
Authentication
Latitude uses HMAC-SHA256 signature-based authentication. All API requests must include a properly formatted Authorization header containing the signature and metadata.
Required Headers
Authorization Header Components
Example: Properly Signed Request
Request:
Expected Headers:
Canonical Request Payload
A plaintext representation of the request, consisting of the following parts (all parts should be included, even if blank):
- Request method
- Request path
- Query params
- Formatted headers, sorted by name
- A sorted list of signed headers, delimited by semicolons
- The SHA256 hash of the request payload
Example:
Signature Calculation
The final signature is generated by:
- Producing a SHA256 hash of the canonical request payload
- Adding the resulting hash to the final payload, and producing a HMAC-SHA256 signature using the secret key
- Encoding the final signature using Base64
Final Payload:
Final Signature:
Base64 Encoded Signature:
Idempotency
The Transfers and Conversion Accounts endpoints support idempotency. This allows you to safely retry requests without accidentally performing the same operation twice. To use it, include an Idempotency-Key header with a UUID value. We recommend a V4 UUID to avoid collisions.
When you supply a valid Idempotency-Key, we save the resulting status code and body and return it for subsequent requests with the same key. When we return a saved result, we include an Idempotency-Replayed: true header in the response.
If the same key is sent with a different request body, the API will return a 409 Conflict error.
Note: Cached responses expire after 24 hours. We recommend generating a new UUID for each unique operation and storing it alongside your internal records so retries use the same key.
Webhooks
Subscribe to webhook events to get real-time notifications about transfer status changes, conversion updates, and KYC results. This is the recommended way to track the lifecycle of your payments.
To create a subscription, send a POST request to /v1/webhook_subscriptions with the URL where you’d like to receive events and the event types you’re interested in.
Request:
Available Event Types
Note: Webhook subscriptions are created at the organization level, not per-individual or per-transfer. Once a subscription is active, you will receive events for all individuals, transfers, and conversions across your account.
Event Type Payload Examples
Every webhook is delivered as a POST request with a JSON body of the form below. The event_type field identifies the event, and event_payload contains the resource snapshot at the time the event fired.
The shape of event_payload depends on the resource the event relates to: transfer events carry a transfer object, conversion events carry a conversion object, and individual.status_changed carries an individual status object. Realistic examples for each event type follow.
transfer.created
Fired when a transfer is created. For transfers funded via a crypto deposit, the payload includes deposit_instructions describing where to send funds.
transfer.funded
Fired once funds are received and the transfer begins processing.
transfer.completed
Fired when the payout settles successfully. completed_in (seconds) and settlement_reference_id are populated.
transfer.failed
Fired when a transfer terminally fails during processing. failure_reason describes the cause.
transfer.expired
Fired when a transfer’s funding deadline passes before funds are received. The transfer never started processing.
conversion.created
Fired when a deposit is received into a conversion account’s virtual account. The blockchain payout has not yet been initiated, so payout timestamps and tx_hash are null.
conversion.payout_initiated
Fired when the blockchain payout to the destination wallet is broadcast. initiated_at and tx_hash are populated; completed_at is still null.
conversion.completed
Fired when the blockchain payout confirms. completed_at is populated.
conversion.failed
Fired when a conversion terminally fails.
individual.status_changed
Fired when an individual’s status changes (for example, as a result of KYC review). status_details lists any action codes with human-readable messages, and is empty when no action is required.
Prefunded Flows
Currently all Latitude flows are prefunded. You send funds to Latitude and those funds settle before you can execute transfers. You can prefund using:
- USD via wire transfer to your Latitude-managed bank account
- USDC via blockchain deposit on the Base network
You can find the instructions for funding your account in the dashboard. We will support more flexible and real-time funding flows in the future.
Sandbox Environment
Latitude provides a sandbox environment for testing your integration without moving real money. Contact us to get sandbox API credentials.
The sandbox supports magic strings for simulating different outcomes (e.g. KYC approval/rejection, transfer success/failure). See the individual integration guides for sandbox-specific details.

