Concepts
Concepts
Five concepts every Crebit Lock integration depends on. Read these once, then refer back to the schemas on API endpoints.
Lock window
The lock window is the time range during which your customer may execute at the locked rate. Two ISO-8601 UTC datetimes define it:
window_start, the first moment the customer is allowed to transact at the locked rate.window_end, the last moment the customer is allowed to transact at the locked rate.
The customer may transact at any moment in [window_start, window_end]. The locked rate is identical at every moment in the window , only the moment the customer picks varies. You set both fields on the quote; the contract inherits them and they're immutable for the life of the lock. Windows can be as short as a few minutes or as long as 180 days.
How long can a window be?
Anywhere from 1 hour (the minimum lock duration) out to 180 days ahead. Two hard rules:
window_end>window_start, no equal values.window_endmust be at least 1 hour after the current time, so the lock window lasts at least 1 hour from when you submit the quote.
| Use case | Typical window |
|---|---|
| Customer wants to transact within hours | Short · 1–6 hours (minimum 1h) |
| Customer expects to transact in the next day or two | Short · 24–72 hours |
| Customer expects to transact within the week | Short · 5–7 days |
| B2B treasury hedging a known upcoming wire | Medium · 2–4 weeks |
| Quarterly settlement, longer-tenor hedging | Long · 30–90 days |
| Maximum allowed | Up to 180 days from now |
Longer windows cost more premium because the customer holds more optionality (more days to pick a favourable market move).
Fields & rules
Lock window
Every quote defines a calendar window during which the customer can execute the locked rate. Always send window_start and window_end:
| Field | Type | Description |
|---|---|---|
| window_start | Datetime (ISO-8601 UTC, e.g. 2026-08-04T13:00:00Z) | First moment the customer may execute the locked rate. Now or any time up to 180 days ahead. Must be strictly before window_end. |
| window_end | Datetime (ISO-8601 UTC, e.g. 2026-08-11T13:00:00Z) | Last moment the customer may execute. Three constraints: (1) STRICTLY AFTER window_start (equal values return validation_error). (2) At least 1 hour AFTER the current time, i.e. the lock window has to last at least 1 hour. Crebit needs that hour of hedging runway before the customer could possibly transact. (3) Within 180 days of now. |
- Both window_start and window_end are required on every quote.
- window_end must be STRICTLY AFTER window_start, equal values are rejected with validation_error.
- window_end must be at least 1 hour AFTER the current time, meaning the lock window has to last at least 1 hour from when the quote is created. Crebit needs that hour of hedging runway. Anything shorter is rejected with validation_error.
- Maximum window: window_end must be within 180 days of now.
- The customer may execute at any moment within [window_start, window_end], the locked rate is identical at every moment in the window.
- Window length affects pricing, longer windows cost more premium (the customer holds more optionality).
- Both contract_type values (forward, option) accept the same window fields.
window_end must be strictly after window_start; equal values are rejected with validation_error.Concrete examples
| Scenario | window_start | window_end | Window length |
|---|---|---|---|
| Shortest allowed (1h from now) | 2026-08-04T09:00:00Z | 2026-08-04T10:00:00Z | 1 hour |
| 3-hour intra-day window | 2026-08-04T09:00:00Z | 2026-08-04T12:00:00Z | 3 hours |
| 48-hour window | 2026-08-04T13:00:00Z | 2026-08-06T13:00:00Z | 48 hours |
| One-week forward | 2026-08-04T00:00:00Z | 2026-08-11T00:00:00Z | 7 days |
| 30-day option | 2026-09-01T00:00:00Z | 2026-10-01T00:00:00Z | 30 days |
| Quarterly hedge | 2026-08-04T00:00:00Z | 2026-11-04T00:00:00Z | 92 days |
| Maximum window | 2026-08-04T00:00:00Z | 2027-01-31T00:00:00Z | 180 days |
validation_error:window_endequal to or beforewindow_start.window_endless than 1 hour after the current time, i.e. a lock window shorter than 1 hour.
Currencies in a quote
Every quote has two currency-related decisions: which FX pair (and which side of it the customer is fixing) and which stablecoin Crebit settles in with you.
Supported directions
We support hedging USD against BRL, MXN, and EUR. Hedging can be done both ways, from USD to the target currency, or the target currency to USD. There are six values for direction:
USD_TO_BRL · BRL_TO_USD · USD_TO_MXN · MXN_TO_USD · USD_TO_EUR · EUR_TO_USD
direction only fixes the FX pair AND which side the trade flows from. Which side of the pair the customer is fixing their amounton, the amount they're sending or the amount they want to receive, is set independently via notional_currency below.
The three fields you send for the currency setup
| Field | What it is | Example |
|---|---|---|
| direction | Which corridor the customer is hedging, and which way the trade flows. One of the six SUPPORTED_DIRECTIONS values above. | BRL_TO_USD, Brazilian importer selling BRL to receive USD. |
| notional_currency | Which side of the pair the notional_amount is denominated in. EITHER side of direction is valid, the customer might be locking the amount they're sending OR the amount they want to receive. The other side is derived automatically and echoed back to you in the response as quote_currency. | For direction=USD_TO_BRL: USD (lock 50,000 USD-worth) or BRL (lock 250,000 BRL-worth), both legal. |
| settlement_currency | Stablecoin Crebit and the partner settle in. Partner sends the upfront fee in this stablecoin to funding_wallet_address; Crebit pays out any FX delta in this stablecoin too. The end customer never sees stablecoins, the partner bills them in local currency and converts. | USDC · USDT · EURC |
Supported chains
| chain | Notes |
|---|---|
| ethereum | Best coverage. USDC, USDT, EURC all available. |
| polygon | Lower fees. USDC and USDT widely available; EURC limited. |
| solana | Fast settlement. USDC native; EURC supported behind a sandbox feature flag. |
Supported stablecoins
| stablecoin | Available on |
|---|---|
| USDC | Default. All chains (ethereum, polygon, solana). |
| USDT | ethereum, polygon. |
| EURC | Best for EUR corridors. solana behind a feature flag. |
Rules
- One stablecoin per contract -
settlement_currencycovers both the partner funding leg and the customer payout leg. - Webhook values must match the contract -
currencyonfunds_in_routemust equal the contract'ssettlement_currency; same forchain. Mismatches return409 contract_mismatch. - Pricing reflects on-chain settlement cost, Ethereum quotes are higher than Polygon all else equal.
Strike, spot, and market rate
Every quote response carries three rates that a partner often confuses. Knowing the difference lets you message your customer accurately, and tells you whether a CIP-fair forward gives them a strike better than today's market (which happens more often than people think).
Three rates that matter
| Field | What it is | Source |
|---|---|---|
| provider_rate | Your live retail FX rate at quote time, what you'd quote the customer with no protection. | You send it on the request. |
| market_rate | The benchmark mid-market FX rate from an independent reference (your data feed or CoinGecko stablecoin pair). | You send it on the request (required). |
| locked_rate | THE STRIKE, the rate the customer actually locks at. For forwards, the CIP-fair forward rate; for options, the option strike. | Crebit returns it. |
Three strike modes
On every quote you choose strike_mode. Omit it and Crebit defaults to cip_fair.
| strike_mode | What Crebit does | Use when |
|---|---|---|
| cip_fair (default) | Derives the CIP-fair forward strike from market_rate + the currency-pair interest-rate differential. When that strike is better than spot for the customer, Crebit funds the difference, paying out the extra settlement_currency (USDC / USDT / EURC) on-chain at exercise so the customer actually receives the better-than-spot rate. | Most quotes. For high-interest-rate corridors (e.g. USD→BRL), the CIP-fair strike sits above spot and Crebit covers the gap in stablecoin, a real selling point for your customer. |
| live_spot | Sets strike = market_rate (today's mid-market exactly). | Customer wants to lock at today's spot. Common for short windows where forward points are minimal anyway. |
| custom | Uses the target_strike value you send. Required field when mode=custom. | Customer specified an exact rate (e.g. ATM/OTM option strike, or matching an external quote). |
How CIP-fair works
Covered interest parity (CIP) says a forward FX rate equals spot adjusted by the interest-rate differential between the two currencies, so the no-arbitrage forward is F = S × (1 + r_quote × t) / (1 + r_notional × t). Crebit applies this from market_rate for the length of the lock window.
quote_currency has higher interest rates than notional_currency (e.g. USD→BRL where BRL rates ≫ USD rates), the CIP-fair forward sits above spot - meaning your customer gets more BRL per USD on the forward than on the live spot today. Use strike_advantage_bps (below) to message how much better.| Response field | Tells you |
|---|---|
| strike_mode | Echoes request: cip_fair · live_spot · custom. |
| target_strike | if strike_mode=custom, the exact target_strike value you sent. |
| strike_advantage_bps | Basis points, customer perspective. Positive = better than market. |
| premium_amount | All-in premium (option) or quoted fee (forward), in settlement_currency. |
| deposit_amount | Security deposit (forwards only; null for options). |
| total_amount | The total amount due to Crebit. Adds premium_amount and deposit_amount. |
strike_advantage_bps explained
The single number you use to tell your customer if the lock is a good deal. Direction-aware, positive always means "customer wins", regardless of which way the FX is going or which strike_mode produced it. Expressed in basis points.
| Example value | Interpretation | Customer messaging |
|---|---|---|
| +220 | Strike is 2.20% better than mid-market. | "You're locking in a rate 2.2% better than today's mid-market." |
| +30 | Slightly better than market. | "Your locked rate is 30 bps above today's spot." |
| 0 | At market (typical for live_spot mode). | "Lock at today's rate, no premium, no discount." |
| −50 | 50 bps premium over market, customer pays for certainty. | "Lock today's rate plus a 50 bps protection premium." |
Which mode to pick
| Scenario | contract_type | strike_mode | Why |
|---|---|---|---|
| Standard forward booking, customer trusts your platform's pricing | forward | cip_fair | Default. Customer usually gets a strike above spot on high-rate corridors. |
| Short window (< 24h) where forward points are negligible | forward | live_spot | Simpler to communicate, "lock today's spot", and indistinguishable from CIP on tiny windows. |
| Forward priced to match a specific invoice / external quote | forward | custom | Send target_strike = the external rate. |
| ATM option, classic vol play | option | live_spot | Strike = market_rate gives a symmetric ATM option. |
| OTM option, cheap insurance | option | custom | Send target_strike past spot in the customer's unfavored direction. Lower premium. |
| ITM option, high-conviction directional bet | option | custom | Send target_strike past spot in the customer's favored direction. Higher premium. |
Crebit prices to whatever mode + strike you specify. Aggressive strikes flow through to a higher premium_amount.
Forward vs option
contract_type picks one of two shapes: forward or option. It's orthogonal to strike_mode, you can combine forwards or options with any of the three strike modes.
| forward | option | |
|---|---|---|
| Upfront cash flow | Security deposit (typically 5-10% of notional) | Non-refundable premium |
| Nature of the upfront | Collateral against the obligation, not a fee | Cost of buying the optionality |
| Customer obligation | Obligated to transact within the window | Right but not obligation |
| If customer DOES exercise | Deposit released back to partner as part of the payout_settled flow | Customer pays nothing more; Crebit pays the FX delta if owed |
| If customer doesn't exercise | Deposit FORFEITED, Crebit keeps it to cover the hedge cost (contract_expired webhook signals this) | Premium was already kept by Crebit; nothing else happens |
| Pricing driver | Time-value over the window | Volatility + time + how aggressive the strike is |
| Best for | Known upcoming transactions, treasury hedging | Optional exposure, FX insurance, uncertain timing |
The two dimensions combine cleanly. Six common combinations:
| cip_fair | live_spot | custom | |
|---|---|---|---|
| forward | Default booking. Strike sits above/below spot depending on rate differential. | Lock at today's spot. Thin premium for delivery certainty. | Forward priced to a specific external rate (e.g. invoice match). |
| option | Option struck at the forward fair. Premium = pure vol. | Classic ATM option struck at today's spot. | ATM / OTM / ITM option, partner picks the strike for the customer's risk appetite. |
Idempotency
Send Idempotency-Key (UUID recommended) on every write. Same key + same body returns the original response within TTL, so retries are safe.
POST /api/v1/fx/quotes, recommended.POST /api/v1/fx/contracts, recommended.POST /api/v1/fx/webhooks/inbound, required (8–256 chars).- Outbound webhooks (Crebit → you): use the
event_idfield as your idempotency key. Crebit may retry the same delivery if your endpoint returns a non-2xx within 10s.
Errors
All errors return a JSON envelope:
{
"code": "validation_error",
"message": "window_end must be after window_start",
"details": {}
}Common code values:
| code | Meaning |
|---|---|
| validation_error | Request body failed schema or business-rule validation. See message + details. |
| market_rate_stale | Sent market_rate is older than PRICING_MARKET_RATE_MAX_AGE_SECONDS (~5 min). |
| notional_limit_exceeded | Requested notional is above your account's per-quote ceiling. |
| contract_mismatch | Chain or settlement_currency on contract_exercised does not match the contract. |
| idempotency_conflict | Same Idempotency-Key replayed with a different body. |