Rebalances
Generated page, from the OpenAPI specification the gateway serves (
GET /v1/openapi.json). Do not edit it by hand: it is rewritten on every build.
| Method | Path | Description |
|---|---|---|
GET |
/v1/rebalances |
List rebalances |
POST |
/v1/rebalances |
Rebalance between your own platforms |
GET |
/v1/rebalances/{id} |
Retrieve a rebalance |
GET |
/v1/settlement-expectations |
List expected card settlements |
POST |
/v1/settlement-expectations |
Announce the expected card settlement |
GET |
/v1/rebalance-requests |
List rebalance requests |
POST |
/v1/rebalance-requests |
Ask treasury for a rebalance |
GET |
/v1/rebalance-requests/{id} |
Retrieve a rebalance request |
GET /v1/rebalances
List rebalances
Same pagination as payments.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
page |
query | no | Page, starting at 1. |
per_page |
query | no | Page size, 100 at most. |
Responses
200— OK (OperationList)401— API key missing or rejected (Error)403— The key does not carry the required scope, or the account is not active (Error)429— The key's request budget is exhausted (300/min) — honour Retry-After (Error)
POST /v1/rebalances
Rebalance between your own platforms
The single-account twin of the internal transfer: moves your own funds from one platform to another. Same conditions as the internal transfer.
Naming both corridors. Each takes either its id or its code — platform_id / platform_code for the source, destination_platform_id / destination_platform_code for the destination. They resolve independently: correcting the source does not paper over a wrong destination.
Naming the pots. platform_account_handle (source) and destination_platform_account_handle (destination) name one specific sub-account by its stable handle, as GET /v1/balances renders it. Absent = the corridor's primary pot, as before. An unknown handle is refused (422 unknown_platform_account), never folded onto the primary.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
Idempotency-Key |
header | no | An idempotency key specific to THIS operation. Replaying the same key with the same payload returns the original; replaying it with a different payload is refused (409). |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
asset_id |
integer | yes | |
amount_minor |
string | yes | Amount in MINOR UNITS, as a string. Never a floating-point number: both lose centimes. The asset's decimal count comes from GET /v1/assets. |
country |
string | yes | ISO 3166-1 alpha-2 |
platform_id |
integer | no | The corridor's numeric id. ⚠️ NOT PORTABLE BETWEEN ENVIRONMENTS: platform ids are assigned by database insertion order, so an id read from sandbox may name a different rail in production. Prefer platform_code. Send either; sending both is accepted only when they agree, and refused with 422 platform_conflict when they do not. |
platform_code |
string | no | The corridor's STABLE code — 'orange', 'wave', 'yas'. Case-insensitive. Means the same platform in every environment, which platform_id does not. Send this or platform_id. |
destination_platform_id |
integer | yes | The platform being credited. |
destination_platform_code |
string | no | The destination corridor's stable code. Resolves independently of platform_code, and refuses its own disagreement with destination_platform_id. |
platform_account_handle |
string | no | Optionnel. Le nom stable du pot SOURCE sur sa plateforme (client_platform_accounts.handle). Absent = le pot principal. |
destination_platform_account_handle |
string | no | Optionnel. Le nom stable du pot DESTINATION, ex. 'neo-card-card-programme'. Absent = le pot principal. Résolu indépendamment de la source. |
client_ref |
string | no | |
description |
string | no |
Responses
201— Rebalance created (Operation)401— API key missing or rejected (Error)403— The key does not carry the required scope, or the account is not active (Error)409— Clé d'idempotence rejouée avec une charge utile différente, ou aucun tarif de virement interne configuré pour cet actif et ce pays (pricing_unavailable) (Error)422— Requête recevable mais refusée : champ manquant, corridor fermé, destination non payable (invalid_destination), pot nommé inconnu (unknown_platform_account), solde insuffisant (Error)429— The key's request budget is exhausted (300/min) — honour Retry-After (Error)503—platform_codemomentarily unresolvable: the platform catalogue cannot be read (temporarily_unavailable). This is not a refusal — send the same request again after Retry-After (Error)
GET /v1/rebalances/{id}
Retrieve a rebalance
The same masked view as GET /v1/payments/{id}.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
id |
path | yes | Internal identifier, the operation's reference, or your own client_ref. |
Responses
200— OK (Operation)401— API key missing or rejected (Error)403— The key does not carry the required scope, or the account is not active (Error)429— The key's request budget is exhausted (300/min) — honour Retry-After (Error)
GET /v1/settlement-expectations
List expected card settlements
Your expectations by settlement date (inclusive bounds), newest first. Without to: today (UTC); without from: 30 days before to; 366 days at most.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
from |
query | no | Premier jour de règlement inclus, YYYY-MM-DD. |
to |
query | no | Dernier jour de règlement inclus, YYYY-MM-DD. |
Responses
200— OK (SettlementExpectationList)401— API key missing or rejected (Error)403— The key does not carry the required scope, or the account is not active (Error)422— Bornes mal formées ou intervalle trop long (Error)429— The key's request budget is exhausted (300/min) — honour Retry-After (Error)
POST /v1/settlement-expectations
Announce the expected card settlement
Announces what the card scheme will debit, on a given day, from the named pot (e.g. the Ecobank card programme account, neo-card-card-programme). neo-pays keeps it awaiting_bank and reconciles the bank statement debit against it. No funds move.
Idempotent on the day and the pot. The same amount for the same (settlement_date, pot) returns the recorded expectation (200), whatever the idempotency key; a DIFFERENT amount is refused (409 expectation_conflict) and never replaces the first.
can_payout scope; a live key requires a live account.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
Idempotency-Key |
header | no | Conservée pour la traçabilité (ex. l'identifiant de votre outbox). L'idempotence porte sur (settlement_date, pot), pas sur cette clé. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
settlement_date |
string | yes | Le jour de règlement, YYYY-MM-DD. |
asset_id |
integer | yes | |
country |
string | yes | ISO 3166-1 alpha-2 |
platform_id |
integer | no | L'identifiant numérique de la plateforme (non portable). Envoyez celui-ci ou platform_code. |
platform_code |
string | no | Le code stable de la plateforme, ex. 'sn-ecobank-senegal'. |
platform_account_handle |
string | no | Optionnel. Le nom stable du pot, ex. 'neo-card-card-programme'. Absent = le pot principal ; inconnu = 422 unknown_platform_account. |
amount_minor |
string | yes | Montant attendu en UNITÉS MINEURES, entier ≥ 0, en chaîne. |
client_ref |
string | no | Votre référence, ex. la référence du rapport de règlement. |
Responses
200— Rejeu : la même attente (même jour, même pot, même montant) était déjà enregistrée (SettlementExpectationResponse)201— Attente enregistrée (SettlementExpectationResponse)401— API key missing or rejected (Error)403— The key does not carry the required scope, or the account is not active (Error)409—expectation_conflict: une attente existe déjà pour ce jour et ce pot avec un autre montant ; le corps porte aussi l'attente enregistrée sousdata(Error)422— Requête recevable mais refusée : champ manquant ou mal formé, plateforme inconnue, pot nommé inconnu (unknown_platform_account) (Error)429— The key's request budget is exhausted (300/min) — honour Retry-After (Error)503—platform_codemomentarily unresolvable: the platform catalogue cannot be read (temporarily_unavailable). This is not a refusal — send the same request again after Retry-After (Error)
GET /v1/rebalance-requests
List rebalance requests
Your requests, newest first, in your key's mode (test or live). can_read_transactions scope.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
status |
query | no | Filtre sur le statut. |
limit |
query | no | 1–200, défaut 50. |
Responses
200— Les demandes (RebalanceRequestList)401— API key missing or rejected (Error)403— The key does not carry the required scope, or the account is not active (Error)429— The key's request budget is exhausted (300/min) — honour Retry-After (Error)
POST /v1/rebalance-requests
Ask treasury for a rebalance
Asks neo-pays treasury to move your claims from one of your pots to another — including into a pot that POST /v1/rebalances refuses (invalid_destination), such as the product PI line or the card programme account. A request, not a move: it joins finance's four-eyes queue; once approved it executes as an ordinary rebalance, which then appears in GET /v1/rebalances (rebalance_id). Only pots on your allow-list can be requested (422 destination_not_allowed).
Idempotent on client_ref. The same body returns the recorded request (200); a different body is refused (409 rebalance_request_conflict).
Tracked by polling (no event): GET /v1/rebalance-requests/{id} every 5 minutes until the status is final (executed, failed, rejected, expired).
can_payout scope; a live key requires a live account.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
amount_minor |
string | yes | Montant en UNITÉS MINEURES, entier > 0, en chaîne. |
asset_id |
integer | yes | |
country |
string | yes | ISO 3166-1 alpha-2 |
source |
object | yes | |
source.platform_code |
string | no | Le code stable de la plateforme, ex. 'neo-card' (ligne PI) ou 'sn-ecobank-senegal'. |
source.platform_id |
integer | no | L'identifiant numérique (non portable). Envoyez celui-ci ou platform_code. |
source.platform_account_handle |
string | no | Optionnel. Le nom stable du pot, ex. 'neo-card-card-programme'. Absent = le pot principal. |
destination |
object | yes | |
destination.platform_code |
string | no | Le code stable de la plateforme, ex. 'neo-card' (ligne PI) ou 'sn-ecobank-senegal'. |
destination.platform_id |
integer | no | L'identifiant numérique (non portable). Envoyez celui-ci ou platform_code. |
destination.platform_account_handle |
string | no | Optionnel. Le nom stable du pot, ex. 'neo-card-card-programme'. Absent = le pot principal. |
reason |
string | yes | Pourquoi (≤ 500 caractères) — lu par la personne qui approuve. |
client_ref |
string | yes | Votre référence (≤ 128), la clé d'idempotence. |
Responses
200— Rejeu : la même demande était déjà enregistrée (RebalanceRequestResponse)201— Demande enregistrée, en attente d'approbation (pending_approval) (RebalanceRequestResponse)401— API key missing or rejected (Error)403— The key does not carry the required scope, or the account is not active (Error)409—rebalance_request_conflict: ceclient_refnomme déjà une demande au corps différent (Error)422— Refusée : champ manquant (invalid_request), plateforme ou pot inconnu (unknown_platform,unknown_platform_account), source = destination (same_pot), destination hors liste d'autorisation (destination_not_allowed) (Error)429— The key's request budget is exhausted (300/min) — honour Retry-After (Error)503—platform_codemomentarily unresolvable: the platform catalogue cannot be read (temporarily_unavailable). This is not a refusal — send the same request again after Retry-After (Error)
GET /v1/rebalance-requests/{id}
Retrieve a rebalance request
The current status of one of your requests: pending_approval → approved → executed (with rebalance_id), or rejected, expired, failed (with failure_code). can_read_transactions scope.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
id |
path | yes | L'identifiant de la demande. |
Responses
200— La demande (RebalanceRequestResponse)401— API key missing or rejected (Error)403— The key does not carry the required scope, or the account is not active (Error)404— Aucune demande de ce compte (et de ce mode) sous cet identifiant (Error)429— The key's request budget is exhausted (300/min) — honour Retry-After (Error)
Schemas
The shapes the operations above return.
OperationList
| Field | Type | Description |
|---|---|---|
data |
Operation[] | |
data[].id |
string | The operation's public id. It is the one in the /v1/payments/{id} paths. |
data[].ref |
string | Our internal, readable reference. Distinct from the id: quote this one to support. |
data[].client_ref |
string | The reference you supplied at creation, returned unchanged. |
data[].kind |
string | payin | payout | withdrawal | refund | chargeback | adjustment | transfer | rebalance. The same object serves all five families; this field says which. |
data[].status |
string | The rail's detailed state. ⚠️ To decide whether the money arrived, read outcome: status carries journey detail and its vocabulary depends on the rail. |
data[].outcome |
string | pending | succeeded | failed | cancelled | expired | reversed. The only field to base a business decision on. |
data[].asset_id |
integer | The operation's asset, by its id (GET /v1/assets). |
data[].amount_minor |
string | The GROSS amount in minor units, as a string. |
data[].fee_minor |
string | The fee taken, in minor units. |
data[].net_minor |
string | The net in minor units: amount_minor less fee_minor. |
data[].platform_id |
integer | The platform that carried the operation. Absent while a hosted collection is still waiting for the payer to choose. |
data[].is_test |
boolean | True for an operation created with a test key. No real money moves. |
data[].payment_url |
string | The hosted payment page, when the rail provides one. Absent until submission has succeeded. |
data[].deeplink |
string | The deep link into the rail's app, when it provides one. |
data[].qrcode_url |
string | The QR to show the payer, when the rail provides one. |
data[].risk |
Risk | The state of the risk check (FRAML). Absent when the operation was not assessed — which is not the same thing as “clear”. The outbound webhook and this read return the same block. |
data[].risk.status |
string | held: the funds have not moved. review: the payment ran its course, something is being looked at. clear: nothing to report. |
data[].risk.case_ref |
string | The operational case reference, to quote to support. Null when the hold is a compliance review. |
data[].risk.case_kind |
string | Accompanies case_ref, or nothing at all. |
data[].risk.reason |
string | The only free text this block carries, and it is identical for every hold. |
data[].risk.signals |
object[] | Product signals, advisory. Absent when there are none. |
data[].risk.signals[].code |
string | |
data[].risk.signals[].detail_fr |
string | |
data[].amount_refunded_minor |
string | Collections only: the sum of SUCCEEDED refunds, in minor units. |
data[].amount_refund_pending_minor |
string | Collections only: the sum of refunds IN PROGRESS, in minor units. |
data[].amount_refundable_minor |
string | Collections only: what can be refunded NOW, in minor units — the original amount less succeeded and in-progress refunds, or "0" when the refund rule allows none (collection not successful, Wave period passed after a partial refund…). |
data[].refund_count |
integer | Collections only: the number of refunds that did not fail. |
data[].partial_refund_deadline |
string | Wave collections only: until when a partial refund is possible (RFC 3339). Absent for other rails, or when Wave partial refunds are disabled. |
page |
integer | |
per_page |
integer |
Error
| Field | Type | Description |
|---|---|---|
error |
object | |
error.code |
string | |
error.message |
string |
Operation
One money operation — collection, payout, refund, transfer or rebalance. The same object across all five families.
| Field | Type | Description |
|---|---|---|
id |
string | The operation's public id. It is the one in the /v1/payments/{id} paths. |
ref |
string | Our internal, readable reference. Distinct from the id: quote this one to support. |
client_ref |
string | The reference you supplied at creation, returned unchanged. |
kind |
string | payin | payout | withdrawal | refund | chargeback | adjustment | transfer | rebalance. The same object serves all five families; this field says which. |
status |
string | The rail's detailed state. ⚠️ To decide whether the money arrived, read outcome: status carries journey detail and its vocabulary depends on the rail. |
outcome |
string | pending | succeeded | failed | cancelled | expired | reversed. The only field to base a business decision on. |
asset_id |
integer | The operation's asset, by its id (GET /v1/assets). |
amount_minor |
string | The GROSS amount in minor units, as a string. |
fee_minor |
string | The fee taken, in minor units. |
net_minor |
string | The net in minor units: amount_minor less fee_minor. |
platform_id |
integer | The platform that carried the operation. Absent while a hosted collection is still waiting for the payer to choose. |
is_test |
boolean | True for an operation created with a test key. No real money moves. |
payment_url |
string | The hosted payment page, when the rail provides one. Absent until submission has succeeded. |
deeplink |
string | The deep link into the rail's app, when it provides one. |
qrcode_url |
string | The QR to show the payer, when the rail provides one. |
risk |
Risk | The state of the risk check (FRAML). Absent when the operation was not assessed — which is not the same thing as “clear”. The outbound webhook and this read return the same block. |
risk.status |
string | held: the funds have not moved. review: the payment ran its course, something is being looked at. clear: nothing to report. |
risk.case_ref |
string | The operational case reference, to quote to support. Null when the hold is a compliance review. |
risk.case_kind |
string | Accompanies case_ref, or nothing at all. |
risk.reason |
string | The only free text this block carries, and it is identical for every hold. |
risk.signals |
object[] | Product signals, advisory. Absent when there are none. |
risk.signals[].code |
string | |
risk.signals[].detail_fr |
string | |
amount_refunded_minor |
string | Collections only: the sum of SUCCEEDED refunds, in minor units. |
amount_refund_pending_minor |
string | Collections only: the sum of refunds IN PROGRESS, in minor units. |
amount_refundable_minor |
string | Collections only: what can be refunded NOW, in minor units — the original amount less succeeded and in-progress refunds, or "0" when the refund rule allows none (collection not successful, Wave period passed after a partial refund…). |
refund_count |
integer | Collections only: the number of refunds that did not fail. |
partial_refund_deadline |
string | Wave collections only: until when a partial refund is possible (RFC 3339). Absent for other rails, or when Wave partial refunds are disabled. |
SettlementExpectationList
| Field | Type | Description |
|---|---|---|
data |
SettlementExpectation[] | |
data[].id |
string | |
data[].object |
string | |
data[].settlement_date |
string | Le jour de règlement (YYYY-MM-DD). |
data[].asset_id |
integer | |
data[].country |
string | ISO 3166-1 alpha-2 |
data[].platform_id |
integer | |
data[].platform_code |
string | Le code stable de la plateforme ; null s'il est inconnu. |
data[].platform_account_id |
integer | Le pot (0 = notre compte de plateforme). |
data[].platform_account_handle |
string | Le nom stable du pot ; null pour le pot principal non nommé. |
data[].amount_minor |
string | Montant attendu en unités mineures ; 0 = aucun règlement ce jour-là. |
data[].client_ref |
string | |
data[].status |
string | awaiting_bank à la création ; matched / unmatched après rapprochement. |
data[].is_test |
boolean | |
data[].created_at |
string | |
data[].updated_at |
string | |
data[].match |
object | Le débit du relevé bancaire rapproché de cette attente ; null tant que status n'est pas matched. Le rapprochement tolère un écart de date (± N jours ouvrés autour de settlement_date) et, si la finance l'a fixée, une tolérance de montant. |
data[].match.statement_ref |
string | La référence stable de la ligne du relevé ( |
data[].match.amount_minor |
string | Ce que la banque a débité, en unités mineures — le montant du déchargement du pot ; peut différer de amount_minor dans la tolérance. |
data[].match.date |
string | La date de comptabilisation de la ligne bancaire (YYYY-MM-DD). |
data[].match.matched_at |
string | |
data[].match.discharge_status |
string | L'écriture qui sort le montant du pot : posted une fois comptabilisée ; refused si le pot ne le couvrait pas (reprise quotidienne). |
data[].match.discharged_at |
string | |
data[].unmatched_reason |
string | Pourquoi l'attente est unmatched (ex. no_bank_debit_within_window) ; null sinon. |
data[].unmatched_at |
string |
SettlementExpectationResponse
| Field | Type | Description |
|---|---|---|
data |
SettlementExpectation | Le règlement carte ATTENDU pour un jour et un pot, tel que l'application l'annonce. Reste awaiting_bank jusqu'au rapprochement du débit correspondant sur le relevé bancaire. |
data.id |
string | |
data.object |
string | |
data.settlement_date |
string | Le jour de règlement (YYYY-MM-DD). |
data.asset_id |
integer | |
data.country |
string | ISO 3166-1 alpha-2 |
data.platform_id |
integer | |
data.platform_code |
string | Le code stable de la plateforme ; null s'il est inconnu. |
data.platform_account_id |
integer | Le pot (0 = notre compte de plateforme). |
data.platform_account_handle |
string | Le nom stable du pot ; null pour le pot principal non nommé. |
data.amount_minor |
string | Montant attendu en unités mineures ; 0 = aucun règlement ce jour-là. |
data.client_ref |
string | |
data.status |
string | awaiting_bank à la création ; matched / unmatched après rapprochement. |
data.is_test |
boolean | |
data.created_at |
string | |
data.updated_at |
string | |
data.match |
object | Le débit du relevé bancaire rapproché de cette attente ; null tant que status n'est pas matched. Le rapprochement tolère un écart de date (± N jours ouvrés autour de settlement_date) et, si la finance l'a fixée, une tolérance de montant. |
data.match.statement_ref |
string | La référence stable de la ligne du relevé ( |
data.match.amount_minor |
string | Ce que la banque a débité, en unités mineures — le montant du déchargement du pot ; peut différer de amount_minor dans la tolérance. |
data.match.date |
string | La date de comptabilisation de la ligne bancaire (YYYY-MM-DD). |
data.match.matched_at |
string | |
data.match.discharge_status |
string | L'écriture qui sort le montant du pot : posted une fois comptabilisée ; refused si le pot ne le couvrait pas (reprise quotidienne). |
data.match.discharged_at |
string | |
data.unmatched_reason |
string | Pourquoi l'attente est unmatched (ex. no_bank_debit_within_window) ; null sinon. |
data.unmatched_at |
string |
RebalanceRequestList
| Field | Type | Description |
|---|---|---|
data |
RebalanceRequest[] | |
data[].id |
string | |
data[].object |
string | |
data[].status |
string | |
data[].asset_id |
integer | |
data[].country |
string | |
data[].source |
object | |
data[].source.platform_id |
integer | |
data[].source.platform_code |
string | |
data[].source.platform_account_handle |
string | |
data[].destination |
object | |
data[].destination.platform_id |
integer | |
data[].destination.platform_code |
string | |
data[].destination.platform_account_handle |
string | |
data[].amount_minor |
string | |
data[].reason |
string | |
data[].client_ref |
string | |
data[].is_test |
boolean | |
data[].rebalance_id |
string | Le rééquilibrage exécuté (GET /v1/rebalances), une fois executed. |
data[].failure_code |
string | |
data[].created_at |
string | |
data[].updated_at |
string | |
data[].executed_at |
string |
RebalanceRequestResponse
| Field | Type | Description |
|---|---|---|
data |
RebalanceRequest | |
data.id |
string | |
data.object |
string | |
data.status |
string | |
data.asset_id |
integer | |
data.country |
string | |
data.source |
object | |
data.source.platform_id |
integer | |
data.source.platform_code |
string | |
data.source.platform_account_handle |
string | |
data.destination |
object | |
data.destination.platform_id |
integer | |
data.destination.platform_code |
string | |
data.destination.platform_account_handle |
string | |
data.amount_minor |
string | |
data.reason |
string | |
data.client_ref |
string | |
data.is_test |
boolean | |
data.rebalance_id |
string | Le rééquilibrage exécuté (GET /v1/rebalances), une fois executed. |
data.failure_code |
string | |
data.created_at |
string | |
data.updated_at |
string | |
data.executed_at |
string |