Integrate
Integrating the credit gate
One call per inbound deposit, before you credit it, with a stable idempotency key and a branch for every outcome.
Read the fail-closed client contract first. This page is the happy path; that page is the one that keeps you solvent when the happy path is unavailable.
Where the call goes
Between “a deposit confirmed on-chain” and “the user’s balance changed”. Not after. Nothing you do afterwards is a control — a reversal is an apology, not a gate.
1 · Build the request
{
"deposit_ref": "deposit-EXAMPLE-0001",
"chain": "example-chain",
"tx_hash": "0xEXAMPLEtxhash000000000000000000000000000000000000000000000000000",
"from_address": "0xEXAMPLEaddress0000000000000000000000001",
"to_address": "0xEXAMPLEaddress0000000000000000000000002",
"asset": "EXAMPLEUSD",
"amount_usd": "25000.00",
"user_ref": "user-EXAMPLE-0001",
"kyc_ref": "kyc-EXAMPLE-0001"
}
Every value above is a synthetic placeholder and is not valid on any chain.
amount_usd is a decimal string, deliberately, so nothing is lost to floating point. user_ref and kyc_ref are your identifiers; Foreshock does not perform or evaluate KYC and stores them only as references.
On chains where the freeze primitive operates on a token account rather than a wallet, state is per token account. Two token accounts of the same wallet can be in different states and must be submitted separately.
2 · Send it with a stable idempotency key
POST /v1/decide/deposit HTTP/1.1
Host: api.foreshock.org
Authorization: Bearer fsk_EXAMPLE_0000000000000000
Idempotency-Key: 22222222-2222-4222-8222-222222222222
Content-Type: application/json
Derive the key from deposit_ref, not from the attempt, so that every retry of this deposit collapses onto the same stored decision.
3 · Read the verdict
{
"decision_id": "11111111-1111-4111-8111-111111111111",
"verdict": "HOLD",
"risk_level": "R1",
"pool": "quarantine",
"reasons": [
{ "code": "ACTIVE_ENFORCEMENT_RELATION", "severity": "R1" },
{
"code": "VENDOR_HIGH_RISK",
"vendor": "example-vendor",
"raw_ref": "cas:sha256:EXAMPLE00000000000000000000000000000000000000000000000000000003"
}
],
"vendor_disagreement": false,
"rule_version": "rules-EXAMPLE-2026.08.01",
"required_actions": ["COLLECT_SOURCE_OF_FUNDS", "L2_REVIEW"],
"sla_deadline": "2026-08-24T13:05:00Z",
"evidence_ref": "cas:sha256:EXAMPLE00000000000000000000000000000000000000000000000000000004",
"billable_units": 1
}
4 · Branch
verdict | What your system does |
|---|---|
CREDIT | Credit. Store decision_id beside the ledger entry. |
HOLD | Do not credit. Route funds per pool. Open the work implied by required_actions, with sla_deadline as the clock. |
REJECT | Do not credit. Route per pool. Open a case. |
Then, regardless of verdict, check the Foreshock-Coverage-Health response header. On degraded, call GET /v1/coverage for detail and record that this decision was taken with reduced visibility.
5 · Route to the pool, and keep the pools apart
pool is clean, tagged, or quarantine. Segregation is the whole point: a quarantine classification that gets swept into the same collection address as everything else has accomplished nothing. QUARANTINE_ROUTE in required_actions is the explicit instruction, but the pool field carries it on every decision.
6 · Complete the required actions, then re-decide
required_actions are steps your workflow completes, not steps we perform. When the reason for the hold was a degradation, the required action is RE_DECIDE_AFTER_RECOVERY — call the endpoint again once the degradation clears.
Call it again with a new idempotency key at that point. You are asking a new question against fresh inputs; reusing the old key would replay the stale answer.
7 · Keep the audit trail
decision_id fetches the evidence bundle from GET /v1/decisions/{decision_id}/evidence. rule_version records which version of your rule set produced the outcome, so the decision can be replayed against the rules that were in force at the time.
Store both next to the ledger entry. The decision record and the snapshot store are what make the gate auditable rather than merely present.
Shadow mode first
Ship the call before you ship the enforcement: send every deposit through the gate, record the verdict, credit as you did before, and compare. A week of that tells you your hold rate, your degradation rate, and whether your operations team can absorb the queue — before a wrong assumption becomes a stuck customer balance.