Collections
Give each user permanent payment details. Every payment converts and pays out on its own.
A collection gives one of your users payment details that never change. Your user saves them once and pays in whenever they like. Each payment converts and pays out on its own. You do not create a quote or an order for each payment.
Collections work in two directions.
| Collection | Your user pays in | Pulse pays out | Collection type |
|---|---|---|---|
| Stablecoin | USDT or USDC to permanent deposit addresses | Naira to a bank account | offramp |
| Naira Coming soon | Naira to a permanent account in their own name | Stablecoin to a wallet address | onramp |
This guide covers stablecoin collections. Naira collections are coming soon. To join as an early partner, contact us.
Stablecoin collections
The user gets permanent deposit addresses, one for each network family. Each deposit becomes an offramp order on its own. Pulse checks the deposit, converts it at the current rate, and pays naira to the collection's payout account.
Add a payout account
Register the bank account that receives the naira. Pulse verifies it with the bank.
Create a collection
Create one collection for each user. The response contains the user's deposit addresses.
Track deposits
Each deposit sends the order webhooks, carrying your collection
reference.
Add a payout account
A payout account is a recipient. Send the bank code and the 10-digit account number. Pulse verifies the account with the bank and returns the registered name. Check the name before you use the account.
curl -X POST "https://engine-api.pilot.pulseshiga.io/v1/recipients" \
-H "X-API-Key: <your key>" \
-H "Content-Type: application/json" \
-d '{
"type": "bank_account",
"is_default": true,
"bank_account": { "bank_code": "058", "account_number": "0123456789" }
}'{
"status": true,
"data": {
"id": "0199d1a4-…",
"type": "bank_account",
"is_default": true,
"bank_account": {
"bank_code": "058",
"bank_name": "GTBank",
"account_number": "0123456789",
"account_name": "ACME SAVINGS LTD"
},
"created_at": "2026-10-15T09:12:40Z"
}
}Get bank codes from GET /v1/banks.
The default account
Set is_default: true on one bank account. A collection created without
recipient_id pays out to the default account. Setting a new default replaces the
previous one.
You can register several accounts and give each collection its own. For example, pay each user's deposits to that user's own bank account.
Delete an account
DELETE /v1/recipients/{id} removes an account. Pulse refuses with
recipient_in_use while a collection uses the account, or while orders paying to it
are not finished. Move those collections to another account first.
Create a collection
Create one collection for each user. Set reference to your own ID for that user,
up to 128 characters.
curl -X POST "https://engine-api.pilot.pulseshiga.io/v1/collections" \
-H "X-API-Key: <your key>" \
-H "Content-Type: application/json" \
-d '{
"reference": "user-48213",
"recipient_id": "0199d1a4-…",
"customer": { "name": "Ada Obi", "email": "ada@example.com" }
}'{
"status": true,
"data": {
"id": "0199d1b7-…",
"reference": "user-48213",
"type": "offramp",
"status": "active",
"recipient_id": "0199d1a4-…",
"customer": { "name": "Ada Obi", "email": "ada@example.com" },
"deposit_addresses": [
{
"address": "0x64e6e8b84beb0ba8ab43a09d4b8a48aa23ecc394",
"networks": ["BASE", "POLYGON", "ARBITRUM", "OPTIMISM", "ETHEREUM", "CELO", "PLASMA"]
},
{
"address": "9S1Pdxe5K6ZRmMZUrZDgig33udTb5TScRehXmYiP69he",
"networks": ["SOLANA"]
}
],
"created_at": "2026-10-15T09:14:02Z"
}
}Leave out recipient_id to pay out to your default account. Without a default
account, the request returns no_default_recipient.
Deposit addresses
Show your user every entry in deposit_addresses. One EVM address serves every
network in its networks list. A Solana address serves SOLANA only. Read the
networks from the response rather than from this page.
The user can send USDT or USDC only where the network supports that asset.
PLASMA supports USDT only. See Supported networks for the assets
on each network.
Send on a listed network
A deposit on a network the address does not list is held, and may not be recoverable.
Reference and retries
reference makes the request safe to retry. Sending the same reference again
returns the existing collection, with the same addresses. Pulse ignores the other
fields on a repeat request. Use PATCH /v1/collections/{id} to change the payout
account.
Customer details
customer.name and customer.email are required. Your user is the person who owns
the addresses.
Track deposits
Each deposit creates an offramp order and sends the order webhooks:
order.payment_received
↓
order.conversion_initiated
↓
order.payout_initiated
↓
order.completed
order.held ← instead, when Pulse cannot process the depositA deposit has no order.awaiting_payment event, because the payment arrives before
the order exists.
Every event carries your collection reference, so you can match each deposit to
your user. order.payment_received also carries the deposit's transaction_hash,
the sender's from_address, and a payout object with the naira amount and rate.
See order.payment_received.
To list a collection's deposits, filter orders by collection_id:
curl "https://engine-api.pilot.pulseshiga.io/v1/orders?collection_id=0199d1b7-…" \
-H "X-API-Key: <your key>"last_deposit_at on the collection shows when its latest deposit arrived.
Held deposits
Pulse holds a deposit it cannot convert automatically, and sends order.held with a
held_reason. The order status is held.
held_reason | Meaning |
|---|---|
unsupported_network | The deposit arrived on a network Pulse does not support. |
unsupported_currency | The asset is not USDT or USDC. |
collection_disabled | The collection was disabled when the deposit arrived. |
below_minimum | The deposit is below 10 USDT or USDC. |
above_maximum | The deposit is worth more than ₦100,000,000. |
no_route | Pulse could not price the deposit at that moment. |
Held funds stay with Pulse. Contact support with the order ID to resolve a held deposit.
Manage collections
| Request | What it does |
|---|---|
GET /v1/collections | Lists your collections, newest first. Filter by reference, status, from, and to. |
GET /v1/collections/{id} | Gets one collection with its addresses. |
PATCH /v1/collections/{id} | Changes recipient_id, or sets status to active or disabled. |
Disabling a collection keeps its addresses. Pulse holds any deposit that arrives
while the collection is disabled. Set it back to active to resume conversions.
A new recipient_id applies to deposits that arrive after the change.
Errors
| Code | Meaning |
|---|---|
account_verification_failed | The bank could not verify the account. Check the bank code and account number. |
recipient_not_found | recipient_id does not match one of your payout accounts. |
no_default_recipient | Send recipient_id, or set a default payout account. |
recipient_in_use | A collection or an unfinished order still uses this account. |
default_recipient_conflict | Another default was set at the same time. Retry. |
collection_not_found | The collection does not exist for your business. |
See Errors and retries for the response shape.