Engineering

Two directions, one primitive

Collecting money and sending money are normally two projects. Two providers, two contracts, two integrations, two reconciliation pipelines, and a treasury process in the middle whose entire job is getting the output of one to become the input of the other.

They are the same primitive pointed in opposite directions. The reason that is not obvious is that most stacks give you no place where the two directions meet.

One leg each

A collection takes local currency or a digital asset from a customer and credits your dollar balance. A payout debits your dollar balance and delivers local currency or a digital asset to a recipient.

# on-ramp — local money in, dollars credited
POST /v1/collections

# off-ramp — dollars debited, local money out
POST /v1/payouts

# both settle against the same balance
GET /v1/balance

On-ramp and off-ramp are the honest names for these. One turns local money into a dollar balance; the other turns a dollar balance back into local money. Everything else — the corridor, the method, whether the customer side is a bank transfer or a phone prompt or an on-chain asset — is a parameter, not a different kind of operation.

The balance is what makes it composable

The shared dollar balance is the whole design, and it is easy to read past because it sounds like an accounting detail.

It is the join. A collection's output and a payout's input are the same denomination, in the same place, with no conversion between them. So chaining the two requires no coordination: you collect, and the money is there, and you pay out. Nothing has to be moved between systems, matched across two providers' statements, or converted at a rate somebody else set.

This is also why the settlement timing matters so much. If a collection took two days to clear, the balance would not be a join — it would be a queue, and you would be back to holding working capital to bridge your own money. That argument is in settlement float is a design decision.

Orchestration is the two composed

Once both directions land on one balance, the interesting endpoint writes itself. An orchestration is a collection and a payout declared as a single request, with the balance in the middle handled for you.

# source → USDC → destination
POST /v1/orchestrate

{
  "source": { "kind": "fiat", "country": "NG" },
  "destination": { "kind": "crypto", "asset_id": "btc-bitcoin" }
}

Each side is fiat or crypto, independently. That is four combinations from one endpoint, and none of them is a special case in the implementation — because underneath, each side is still just a leg, and the hub is still the same balance.

Which is why adding a market does not change your code. A new corridor is a new value in an existing field, not a new integration. Your request shape was never corridor-specific to begin with.

You never hold the settlement asset

The hub is a stablecoin rail. This is worth being precise about, because it is the part people assume has consequences for them.

It does not. Your balance is denominated in dollars. You do not custody a stablecoin, you do not sign a transaction, you do not manage a key, and there is no wallet in your integration. The rail is how value moves between the two legs — a settlement mechanism, in the same category as the correspondent banking you also never think about when you send a wire.

The difference is that this one settles in seconds and works on a Sunday, which is what makes the two legs feel like one operation rather than two.

What this buys an integration

Concretely: one set of credentials, one balance to monitor, one transaction model, one reconciliation pipeline, and one timeline format across every direction and every market.

The alternative is not worse because it is more code. It is worse because the code is per corridor, and that is the quantity that grows when the business does. Wire two endpoints and the second market costs nothing; wire two providers per corridor and the fiftieth market costs what the first one did.

Endpoint references are in the docs, and the common flows are in the recipes. Questions: hi@spendfigo.com.

Common questions

What is the difference between a collection and a payout?

Direction only. A collection converts local currency or a digital asset into your dollar balance; a payout converts your dollar balance into local currency or a digital asset for someone else. Both are one leg against the same balance.

What is an on-ramp and an off-ramp in payments?

An on-ramp turns local money into a digital dollar balance. An off-ramp turns that balance back into local money. Naming them as opposite directions of one primitive is what makes them composable rather than two separate integrations.

Do I need to hold stablecoins to use a stablecoin settlement rail?

No. The rail is how value moves between the two legs. Your balance is denominated in dollars, and the settlement asset is an implementation detail you never custody or handle.

← All engineering writing