Transfers API
A transfer reference is public text attached to a ZCHF transfer, such as an invoice number, order ID or payment purpose. The Transfers API indexes reference-bearing transfers so an application can find recent activity and identify payments to verify against an invoice.
Ordinary ERC-20 transfers without references are outside this dataset. An indexed match is a candidate, not proof of payment settlement; the invoice workflow explains the checks needed before crediting it.
Endpoints and response shapes
/transfer/reference/list
{num, list}
Cached observations, not a complete ledger or reliable cursor
/transfer/reference/counter
Number
Not a reliable high-water mark
/transfer/reference/by/count/:count
One record or an error
A missing record is not proof of no transfer
/transfer/reference/by/from/:from
Array
Cached outgoing matches
/transfer/reference/by/to/:to
Array
Cached incoming matches
/transfer/reference/history/by/from/:from
Array
Indexed history, capped at 100 rows, no exposed cursor
/transfer/reference/history/by/to/:to
Array
Same cap and completeness limitation
The opposite-party filter is to on sender routes and from on recipient routes. reference is an exact, case-sensitive match, not substring search. Encode query parameters with URLSearchParams. Do not interpolate reference text into a URL. References are public, untrusted text; render them as text, not HTML, and never include secrets.
Find transfers for an account
For a recent-activity view, choose /by/from/:from for outgoing transfers or /by/to/:to for incoming transfers. For an invoice search, add the other party and the exact reference string. The history routes add a time window, but cap the result at 100 records without a cursor.
For example, this request searches indexed outgoing history for one exact reference:
curl --fail --get 'https://api.frankencoin.com/transfer/reference/history/by/from/0x963eC454423CD543dB08bc38fC7B3036B425b301' \
--data-urlencode 'reference=12 months loan'Read each row's recipient, source chain, amount and targetChain as well as its reference. The candidate lookup adds an expected recipient and time window and checks the response against the invoice requirements.
Time ranges and errors
Use ISO dates or explicit UTC ISO timestamps for history start and end. The range has an inclusive start and exclusive end after the API converts the dates to seconds. Whole-second UTC boundaries avoid rounding ambiguity.
Numeric Unix-second query strings can produce an error payload even with HTTP 200; use the ISO form above and check the payload shape. An error, timeout, null row or malformed response means data unavailable, never “no payments”. An empty valid array means no indexed matches in that response, not a complete absence of payments.
Counter and completeness limitations
The counter is not a reliable high-water mark. Do not use counter increases, ordering or count > lastCount as a notification/payment cursor. Refresh the relevant account query for a recent-activity display and retain its incomplete-history status. Latest caches and capped history can omit records; splitting time ranges alone cannot prove completeness when 100 events share a boundary.
For a complete ledger, use a separately validated indexer or the relevant contracts' logs via an RPC with explicit block-range pagination, persisted checkpoints, reorg handling and reconciliation against receipts. Verify each supported chain, contract deployment block and event ABI. Do not label an API-only export complete.
Record fields
amount
Decimal integer string in ZCHF base units (18 decimals)
chainId
Number: source EIP-155 chain ID
count, created
Decimal integer strings; the specification also allows numbers. created is Unix seconds. Preserve count without floating-point coercion
from, sender, to
Addresses; from and original sender can differ. Validate before case-normalised comparison
reference
Exact public reference string, possibly empty
targetChain
Decimal string: 0 is the same-chain sentinel; otherwise a CCIP chain selector, not an EIP-155 ID
txHash
Full source-chain transaction hash
Keep CCIP selectors as strings or BigInt; some exceed JavaScript's safe integer range. Resolve nonzero selectors against the maintained CCIP configuration for the relevant deployment. Never compare chainId !== targetChain to detect destination settlement. A source-chain reference event does not establish receipt on the destination chain.
Invoice integration boundary
A reference/amount match is only a candidate for verification. This API record does not supply the token-emitting address, log index, receipt success, confirmations, or destination settlement proof needed to authorise delivery.
Before crediting a payment:
Require the intended recipient, payer policy, exact invoice identifier, chain, token contract and integer amount. Reject underpayment; handle partial/overpayments under an explicit business policy.
Fetch and validate the successful transaction receipt on the expected chain. Decode the correct contract's reference and token events and bind them to each other; matching a hash alone is insufficient.
Apply a chain-specific finality/reorg policy. For bridges, verify destination token, recipient and settlement independently.
Deduplicate by
(chainId, txHash, logIndex), persist allocation to the invoice atomically, and prevent reuse for another invoice. APIcountis not a substitute for a verified event identity.Keep unavailable, no-indexed-match, candidate and verified-settlement states distinct. No API-only path in this guide returns
paid.
Candidate lookup example
This example accepts only same-chain candidates and never reports paid. It matches one transfer against the full invoice amount; it does not aggregate partial payments. Duplicate API rows are collapsed for display only. Receipt-level event deduplication and invoice allocation remain separate.
Pass an invoice object containing from, to, chainId, reference and a decimal integer-string amount in ZCHF base units to historyCandidates, along with whole-second UTC ISO start and end timestamps. It returns unverified-candidates when rows meet those requirements, or no-indexed-match when none do. Both results have complete: false; malformed or unavailable responses throw. Send candidates to the receipt-verification stage, not directly to order fulfilment.
See API conventions for units and shared validation.
Last updated
Was this helpful?