# Flow — Aurumsys API

The payment journey, drawn: who calls whom, what the orchestrator does inside every request, and where a transaction can end up. Three views — payin, payout and refund. The integration guide is the contract; this page is the map.

## Payin — money coming in

One call from you. We pick the provider, watch the payment, and tell you when it is settled.

**Who takes part:** Your platform (your backend, holding your API key) · Aurumsys (the orchestrator: one API in front of every provider) · Provider A (first in your routing order for this method and currency; Provider B: second · takes over if A refuses; Provider C: third) · Payer (your customer, in their browser).

### The journey

1. **Your platform → Aurumsys:** Create the payin: `POST /v1/payins`, with an `Idempotency-Key`.
2. **Aurumsys → Provider A:** Route the payin to the first provider in your routing order for this method and currency.
3. **Aurumsys → Provider A:** If Provider A refuses in a way another provider could take, and your cascade setting allows it, the same payment is offered to Provider B — same id, one answer.
4. **Provider A → Aurumsys:** The provider answers with its payment page link.
5. **Aurumsys → Your platform:** 201 with status `PENDING` and a `redirectUrl`.
6. **Your platform → Payer:** Send the payer to `redirectUrl`, as a top-level navigation.
7. **Payer → Provider A:** The payer pays on the provider page.
8. **Provider A → Aurumsys:** The provider notifies us that it is paid; we verify the notice before it counts.
9. **Aurumsys → Your platform:** Signed callback with status `COMPLETED`. Settle your books here.
10. **Payer → Your platform:** The payer's browser returns to your `returnUrl`. It is a page to show, not a payment result.

### Inside every request

- **Verify.** Your API key and its scope are checked before anything else happens.
- **Once only.** The same `Idempotency-Key` never creates a second payment. A repeat gets the first answer again.
- **Ask you first.** Optional. With the hook on, we ask your endpoint before any provider is touched. A no stops here.
- **Route.** Your routing order picks the provider for this method and currency.
- **Cascade.** A provider that refuses can be followed by the next in your order. Same id, one answer, every attempt on record.
- **Watch.** Provider notices are verified before they count. An unclear answer is re-checked with the provider until it is sure.
- **Tell you.** Every status you could not have learned yourself arrives as a signed callback, retried with backoff until you answer.

### Where a payment can be

- `CREATED` moves to one of the waiting states: `PENDING`, `PROCESSING` or `IN_DOUBT`.
- A waiting state can move to another waiting state before it settles.
- Any waiting state can end in any of the three terminal states: `COMPLETED` (settle), `FAILED` (show the reason) or `CANCELLED`.
- `IN_DOUBT` is not a failure. It waits for the provider's answer and often ends `COMPLETED`. Never re-send it.
- `PENDING` may become `EXPIRED` — our guess that an abandoned page will never be paid. An `EXPIRED` payin may still become `COMPLETED` or `FAILED` if it is paid late after all.
- A `FAILED` payin may still become `COMPLETED` inside a provider's provisional window, on the slow rails that declare one.
- `COMPLETED` and `CANCELLED` are final. A won dispute arrives as a new reversal, never as a status flip.
- Apply a late status change to a row you had already closed; do not reject it as impossible.

Every callback is signed. Every provider attempt is on the payment. Nothing settles on the browser coming back.

Read more: [integration guide](https://docs.aurumsys.com/guide/index.md#4-the-hosted-payment-page-flow).

## Payout — money going out

Check the destination first if you like. Then one call, and it executes at once — no approval step on our side.

**Who takes part:** Your platform (your backend, with a money-moving API key) · Aurumsys (the orchestrator: checks the destination, picks the rail, follows the money) · Provider A (first in your order for this rail and currency; Provider B: second · takes over if A refuses; Provider C: third) · Recipient (your customer's bank account, card or wallet).

### The journey

1. **Your platform → Aurumsys:** Optional dry run: `POST /v1/payouts/validate` with the same body as the payout.
2. **Aurumsys → Your platform:** The answer is valid, or names the exact field to correct. No transaction exists yet and no `Idempotency-Key` is consumed.
3. **Your platform → Aurumsys:** Create the payout: `POST /v1/payouts`, with the destination and an `Idempotency-Key`.
4. **Aurumsys checks:** The destination shape and the route limits are checked. A wrong-shaped account is refused before any transaction exists, so the correction can go out under the same `Idempotency-Key`.
5. **Aurumsys → Provider A:** Route the payout to the first provider in your routing order for this rail and currency.
6. **Aurumsys → Provider A:** If Provider A refuses outright, and your cascade setting allows it, the same payout is offered to Provider B — same id, one answer. Never after money may have moved.
7. **Provider A → Aurumsys:** The provider accepts the payout.
8. **Aurumsys → Your platform:** 201 with status `PROCESSING`: the provider is executing it.
9. **Provider A → Recipient:** The provider sends the money. Some rails first show the recipient a page (`redirectUrl`) to collect or confirm details.
10. **Provider A → Aurumsys:** The provider notifies us that it is paid out; we verify the notice before it counts.
11. **Aurumsys → Your platform:** Signed callback with status `COMPLETED` — or `FAILED`, with the reason and what to do.

### Inside every request

- **Verify.** Your API key must be a money-moving one. A read-only key is refused before anything else.
- **Once only.** The same `Idempotency-Key` never pays twice. A retry after a timeout gets the first answer again.
- **Check the destination.** Each rail publishes the exact shape it wants. A mistyped account costs one corrected keystroke, not a failed payout.
- **Route.** Your routing order picks the provider for this rail and currency.
- **Cascade.** A provider that refuses outright can be followed by the next in your order. Never after money may have moved.
- **Watch.** An ambiguous answer parks the payout as `IN_DOUBT` and we ask the provider until it is sure. Nothing is sent twice.
- **Tell you.** `COMPLETED` or `FAILED` arrives as a signed callback. A failure says what to do: retry later, try another method, or stop.

### Where a payout can be

- `CREATED` moves to `PROCESSING`. There is no `PENDING` in the normal case, because nobody is waiting on a page.
- `PROCESSING` and `IN_DOUBT` can move between each other before the payout settles.
- Either can end `COMPLETED`, `FAILED` or `CANCELLED`.
- `IN_DOUBT` is not a failure: it often ends `COMPLETED`. Never re-send it.
- `COMPLETED` and `CANCELLED` are final.
- A returned payout arrives later as a `REVERSAL` you did not create (`reversalKind` `PAYOUT_REVERSAL`), with its own signed `transaction.reversed` callback.

A payout executes immediately. Check the destination first, send once, and settle on the signed callback.

Read more: [integration guide](https://docs.aurumsys.com/guide/index.md#checking-a-destination-before-a-payout).

## Refund — money going back

A refund is something you ask for, against one payin. A reversal is something that happens to you — we tell you, signed.

**Who takes part:** Your platform (names the payin to refund, and optionally an amount) · Aurumsys (keeps the ledger of what is still refundable on each payin) · Provider A (the one that took the payin. The refund follows it; Provider B: not consulted; Provider C: not consulted) · Payer (gets the money back where it came from).

### The journey

1. **Your platform → Aurumsys:** Refund the payin: `POST /v1/refunds` with the payin as `parentTransactionId`, an `Idempotency-Key`, and optionally an amount (omit it for the full remainder).
2. **Aurumsys checks:** The payin must be `COMPLETED` and the amount must fit what is still refundable — earlier refunds and reversals count. The check runs under a lock, so two concurrent refunds cannot both fit.
3. **Aurumsys → Provider A:** The refund goes to the provider that took the payin. It is never routed and never cascades.
4. **Provider A → Aurumsys:** The provider accepts the refund.
5. **Aurumsys → Your platform:** The answer is `PROCESSING`, or `COMPLETED` at once — per provider. Read the status; do not assume.
6. **Provider A → Payer:** The provider returns the money to the payer.
7. **Provider A → Aurumsys:** The provider notifies us that it is refunded; we verify the notice before it counts.
8. **Aurumsys → Your platform:** Signed callback with status `COMPLETED`; `parentTransactionId` names the payin.

### When money is taken back instead

chargeback · recall · returned payout · fraud claim: a `REVERSAL` nobody on your side created.

1. **Their bank → Provider A:** The money is taken back: the payer disputed it, or the rail returned it.
2. **Provider A → Aurumsys:** The provider notifies us, and we create the `REVERSAL`. No endpoint creates one, and there is nothing to acknowledge.
3. **Aurumsys → Your platform:** Signed `transaction.reversed` callback. `reversalKind` says which kind it is; read it, do not derive it. A reversal against a payin consumes the same refundable remainder as refunds do.
4. **Aurumsys → Your platform:** A dispute won later arrives as a new reversal the other way (`reversalKind` `CHARGEBACK_WON`), never as a status flip on the old one.

### Inside every refund

- **Verify.** A money-moving key, checked before anything else.
- **Once only.** The same `Idempotency-Key` never refunds twice. A retry gets the first answer again.
- **Against the payin.** Only a `COMPLETED` payin, only up to what is still refundable — earlier refunds and reversals already taken off.
- **Same provider.** A refund follows the payin to the provider that took it, with the settings of that day. No routing, no cascade.
- **Tell you.** Some providers settle inside the answer, others later by signed callback. Either way `parentTransactionId` names the payin.

Refunds and reversals draw from the same remainder. Treat them as the same thing and you pay the same money out twice.

Read more: [integration guide](https://docs.aurumsys.com/guide/index.md#10-refunds-and-chargebacks).
