One integration. The whole registry.
Issue, hold, transfer, and verify eInstruments over plain HTTPS + JSON. Every response is post-quantum signed (NIST FIPS 204 · ML-DSA-65) and anchored in a hash-chained audit ledger — evidence-grade by design, independently re-verifiable by anyone.
Base URL: https://iset.finance/api
sandbox — fully signed, fully verifiable, no legal effect. Production issuance follows issuer qualification (KYI).Authentication
Two levels, by design:
Public — no credentials
Verification is public. Anyone holding a record's reference may confirm it — that is the point of a registry.
Session — passkey sign-in
Issuing, listing, and transferring act on your records, so they require your account session. Sign in at /console/ with a passkey, then send the session token:
# the dashboard does this automatically; direct callers send:
Authorization: Bearer <session_token>
The lifecycle
A record moves through controlled states. Every transition is a signed, audit-anchored event; invalid transitions are refused by the registry.
pledge grants a lender control during a credit term · release returns it · transfer passes control to a new holder (MLETR-aligned §10 for transferable records) · discharge ends the instrument — terminal, irreversible.
Compose a request
Configure a record on the left — the exact API request builds itself on the right. Copy it, or sign in to issue it for real.
Verify a record
Confirms a record by its reference: what it is, its current status and holder, and the signature that proves it. This is what a bank officer reaches when scanning a record's QR.
curl https://iset.finance/api/etr/verify/fvt_9f40e226_87a14068
{
"ok": true, "verified": true,
"record": {
"etr_id": "fvt_9f40e226_87a14068",
"instrument": "ePN", "instrument_name": "Electronic Promissory Note",
"amount": "2500000", "currency": "PHP",
"status": "registered", "holder_ref": "phase2-test",
"history": [], "sandbox": true,
"signature": "ML-DSA-65:…", "record_hash": "sha-256:…"
},
"brand": null
}
Issue an eInstrument
Issues a record under your account: signed at the root, entered in the registry, owned by you, verifiable by anyone holding its reference.
| Field | Type | Description |
|---|---|---|
| type required | string | One of ePN · eBE · eBL · eLC · eWR · eCI |
| amount | string | Face amount |
| currency | string | Default PHP |
| holder_ref | string | The first holder — person or institution |
| memo | string | Terms or note, ≤ 500 chars |
| fields | object | Per-instrument particulars — parties, voyage, cargo, terms. Schema: /assets/etr-schemas.js. Stored and rendered on the certificate. |
curl -X POST https://iset.finance/api/etr/issue \ -H "Authorization: Bearer <session_token>" \ -H "Content-Type: application/json" \ -d '{"type":"ePN","amount":"2500000","currency":"PHP","holder_ref":"Juan Dela Cruz"}'
{ "etr_id": "fvt_…", "status": "registered", "signature": "ML-DSA-65:…",
"court_admissible": true, "verify_path": "/v1/etr/verify/fvt_…" }
List records
Your records, newest first — references, statuses, holders, and signatures. Listing is private: there is no public index of the registry.
{ "ok": true, "count": 2, "records": [ … ] }
Transfer control
Acts on a record you own. Each action is a signed event; the registry enforces valid transitions and refuses anyone but the owner.
| Field | Type | Description |
|---|---|---|
| etr_id required | string | The record's reference |
| action | string | transfer (default) · pledge · release · discharge |
| to_ref | string | Who receives control — required for transfer and pledge |
| note | string | Optional, ≤ 300 chars — entered in the audit event |
curl -X POST https://iset.finance/api/etr/transfer \ -H "Authorization: Bearer <session_token>" \ -H "Content-Type: application/json" \ -d '{"etr_id":"fvt_…","action":"pledge","to_ref":"Partner Bank A"}'
{ "isp_name": "ETR_CONTROL_PLEDGE", "status": "pledged",
"holder_ref": "Partner Bank A", "signature": "ML-DSA-65:…" }
403; an invalid transition (for example pledging a pledged record) gets 409; a discharged record refuses everything.Subscriber profile
Your account profile — name, account type, branding (colour · logo · verify destination), tier, packs. The same profile drives the white-label certificate at /record/<reference>.
Updates the profile. Send only the fields you change; logos are data-URLs ≤ 200 KB.
Audit retrieval
Retrieves a signed event from the hash-chained ledger and re-verifies its signature against the published key on read. The public key lives at /.well-known/ml-dsa65-public.json — you can check the mathematics yourself.
Model Context Protocol
An AI client can verify records and read the instrument schemas without an integration. Point any MCP client at the endpoint below — no SDK, no account, no key.
https://iset.finance/mcpJSON-RPC 2.0. A GET returns the discovery document to a client and a
readable page to a browser, so the same URL serves both.
Tools
| Tool | Returns |
|---|---|
verify_record | Whether a record is real, who holds it, its status and audit anchor |
list_instruments | The twelve instrument types, their legal basis, negotiability class, and which are transferable under MLETR |
get_instrument_schema | Parties, particulars and lifecycle for one instrument |
get_instrument_lifecycle_state | The status of one record — raw state, its band, and what it means commercially |
verify_cif_set | Invoice + bill + insurance checked as one set — cross-references and the UCP 600 art. 28 arithmetic |
check_counterparty_limits | Whether a counterparty profile exists and what limits it records — never a fabricated pass |
describe_registry | What the registry is and is not — use before asserting anything about ISET |
Connect a client
{
"mcpServers": {
"iset-etr": { "url": "https://iset.finance/mcp" }
}
}
Try it by asking your client to verify EPN-2026-SAMPLE-0001 — or run every call yourself in the sandbox, no signup, with the well-known sandbox key iset_sandbox_demo_v1.
On-chain settlement
The control layer is chain-portable by design — the registry record is chain-agnostic, and each network gets its own anchoring contract. Stellar is the first supported network.
The registry above is the system of record for terms and identity. A separate, public control layer runs on Stellar (Soroban): the epn_escrow contract governs who holds a note — exclusively, one holder at a time — and its full lifecycle through endorsement, settlement, or default. The contract never custodies or moves funds; it enforces control. The two layers are deliberately decoupled — the registry operates standalone without it (see deployment spectrum).
The reference application is live at stellar.iset.finance — issue, endorse, accept, settle, and verify against real wallets, no account needed.
Issues and post-quantum signs a record for the Stellar app: validates the instrument code against the six-type allow-list and the stellar_pubkey format, then registers the record and returns its signature and audit anchor. CORS-enabled for stellar.iset.finance.
{ "etr_id": "fvt_…", "record_hash": "sha-256:…",
"signature": "ML-DSA-65:…", "audit_id": "aud_…", "sandbox": true }
The epn_escrow contract
Rust / Soroban. Every state transition requires the acting party's on-chain authorization and emits an event. Endorsement is a two-signature handshake — offer by the current holder, acceptance by the named endorsee — so transfer of control is bilateral, exclusive, and provable.
| Function | Who may call | Effect |
|---|---|---|
| init | maker | Registers terms (maker, holder, amount, maturity) · status Active |
| endorse | current holder | Offers control to a named endorsee — revocable until accepted |
| accept | named endorsee | Takes exclusive control; previous holder loses all authority |
| release_funds | current holder | Settles the note · terminal Released |
| claim_default | maker, after maturity | Reclaims a matured, unsettled note · terminal Defaulted |
| terms · status · pending | anyone | Read views — no wallet, no credentials, via transaction simulation |
Unauthorized); a settled or defaulted note refuses every further action (NotActive); default before maturity is refused (NotMatured). These refusals hold regardless of who operates the registry.Deployments
| Network | Contract | State |
|---|---|---|
| Testnet | CDZMFQBSZO44IX5TMHY55PYG6I3JOUEZFWSRMFJCUAF2AKWOOWX2H3IT | Full lifecycle incl. two-party endorsement — the live demo network |
| Mainnet | CBDFHJ2V7YBQGF4PNDPTKAALHIE6PYRBL6PVAGMJA5OFFEUMHJYQLL7O | Issue + settle live; the endorsement upgrade is staged and pending deployment |
For institutions — legal posture & integration
Legal posture, stated precisely
Records issued here have legal standing as electronic documents and signatures under the Electronic Commerce Act (RA 8792) — an electronic record is not denied validity for being electronic. What RA 8792 does not settle is full negotiable-instrument status: the electronic equivalent of indorsement and delivery. That is precisely what the UNCITRAL MLETR codifies — and the Philippines has not yet enacted it.
Our position is therefore deliberate: we built the control architecture MLETR's test requires — a single authoritative record of control, exclusive control enforced by contract, integrity by hash-chain and signature, and an identifiable current holder — so records are MLETR-ready ahead of recognition, not claimed compliant before it. For secured lenders, the Personal Property Security Act (RA 11057) is the operative hook today: §19 ranks possession/control of an instrument above registration when perfecting a security interest — and on-chain exclusive control is the electronic analogue of possession.
Deployment spectrum — fiat-first, chain-optional
Records are fiat-denominated (PHP by default), and because the settlement contract never custodies funds, actual payment has always run on a separate rail — which can be InstaPay, PESONet, a bank transfer, or a wallet, with the payment reference entered into the signed audit event. That makes two deployment modes real today, not roadmap:
| Mode | What runs | Enforcement | Trust model |
|---|---|---|---|
| Registry standalone | This API only — issue, transfer, verify; fiat settlement on your existing rails; no crypto exposure, no wallet UX for your users | Lifecycle refusals enforced as policy by the registry | Tamper-evident: signatures + hash-chain make alteration detectable; you trust ISET as operator |
| + Chain anchoring | The same records, control additionally enforced by the Soroban contract | Refusals enforced as structure — they hold even against the registry operator | Tamper-proof exclusivity: no one, including ISET, can double-pledge a note |
An institution can start registry-only — zero blockchain touch — and enable anchoring later without re-architecture, because the layers were never coupled. One honest caveat: in registry-only mode, the RA 11057 §19 control-as-possession argument is softer — control enforced by an operator's server is a weaker form of "possession" than contract-enforced control. We state that before counsel asks.
Integration paths
| Path | What it is | Starts with |
|---|---|---|
| Pilot | One corridor, one instrument, measured against agreed success criteria — free at design-partner stage | A scoping conversation |
| API | Server-side keys under an issuer agreement — issue, transfer, and verify from your own systems | Issuer qualification (KYI) |
| White-label | Your brand on the records and certificates your customers see — branding is already live in the subscriber profile | An issuer agreement |
Download the institutional brief → — a one-page summary built for internal circulation: what this is, proof of deployment, legal posture, pilot shape, and known limits.
Contact: trust@iset.finance
Errors
| Status | Body | Meaning |
|---|---|---|
| 401 | auth_required | No valid session — sign in at /console/ |
| 403 | Only the record owner… | The session's account does not own this record |
| 404 | No record for that reference. | Reference not in the registry |
| 409 | Cannot <action> a record in status… | Invalid lifecycle transition |
| 413 | payload_too_large | Body exceeds the limit |
| 502 | upstream_unreachable | The engine could not be reached — retry |
