Developer reference · Contract 1.0 · Protocol v2

x402 API Developer Guide

Integrate with Zahlen's isolated x402 gateway, merchant policy, observability, reconciliation, visibility, CSV import, and audit-evidence interfaces. This guide documents the API that is implemented today and clearly marks the boundary between deterministic test payments and gated real-facilitator connections.

Current Implementation Status

The API described here is complete for simulated x402 payments, policy evaluation, immutable event recording, merchant visibility, reconciliation, CSV ingestion, and audit exports. The dashboard and prototype still use DeterministicLocalFacilitator. It makes no network calls and moves no money. A Coinbase CDP live adapter is implemented behind the provider-neutral interface, but it is not registered with the gateway or enabled by default.

Canonical contractVersion 1.0 append-only Zahlen records.
x402 protocolVersion 2 request, challenge, proof, verification, and settlement models.
Test networklocal:zahlen-test using the synthetic ZTEST asset.
First live adapterCoinbase CDP for the exact scheme on Base Sepolia and Base; present but not connected.
Live payments remain disabled by default Do not treat prototype settlement responses as proof that money moved. A separately reviewed live adapter and an approved production rollout are required for monetary use.

Coinbase CDP Facilitator Adapter

Zahlen's first real-provider adapter uses Coinbase CDP's hosted x402 facilitator. It sends the standard x402 version 2 payment envelope to the provider for verification and settlement. The rest of Zahlen continues to use the same provider-neutral records, policy decisions, reconciliation, and audit evidence.

Schemeexact
Test networkBase Sepolia, eip155:84532
Live networkBase, eip155:8453
Provider endpoints/platform/v2/x402/verify and /platform/v2/x402/settle

Runtime configuration

Install the optional x402-live package group and load the following values from the approved deployment secret manager. Never place these values in code, CSV files, URLs, logs, screenshots, dashboard fields, or audit records.

SettingPurpose
ZAHLEN_X402_CDP_API_KEY_IDIdentifies the Coinbase CDP Secret API Key used to create short-lived request tokens.
ZAHLEN_X402_CDP_API_KEY_SECRETSigns the short-lived provider request token. It stays in runtime memory and is never a Zahlen payment record.
ZAHLEN_X402_CDP_TIMEOUT_SECONDSOptional request timeout. The default is 10 seconds; accepted values are 0.1 through 30 seconds.
Implementation does not mean activation The adapter remains unavailable until deployment code explicitly registers it, the existing registry is given live-adapter permission, the live-payment flag is enabled, merchant challenge terms are reviewed, and the production-readiness gate passes.

Provider authentication, rate limits, rejected requests, timeouts, outages, and invalid responses become short deterministic reason codes. Raw provider response bodies and credential values do not cross the adapter boundary. Zahlen withholds the resource when verification or settlement cannot be trusted.

Environments and Feature Flags

EnvironmentBase URLIntended use
Developmenthttps://zahlenfinancial.comDashboard review, example data, and approved integration testing.
Productionhttps://zahlenfinancial.comMerchant visibility and deployed application access. Prototype and live-payment flags remain off unless explicitly approved.
Local testhttp://localhost:<port>Deterministic lifecycle tests with no monetary value.

Prototype flag

ZAHLEN_X402_PROTOTYPE_ENABLED=true enables routes under /v1/x402/prototype. Use this only in an approved local or test environment. When it is absent or false, prototype routes fail closed with HTTP 404.

Live-payment flag

ZAHLEN_X402_LIVE_PAYMENTS_ENABLED=true is one part of the future live-adapter gate. The flag alone cannot create live support. A registered live adapter, capability match, operational approval, and production-readiness evidence are also required.

Authentication and Merchant Scope

The x402 surfaces use three authentication patterns.

Agent-facing resourceThe prototype protected-resource route accepts an x402 proof header. It does not use the merchant API key.
Merchant APITimeline, reconciliation, policy, visibility, identity, and API evidence routes require X-API-Key.
Operator dashboard APIRoutes under /admin/x402 use the authenticated browser session and tenant security context.

Merchant API-key header

X-API-Key: <merchant-api-key>

The API key is resolved to one merchant and tenant. The merchant_id in the URL must match that identity. A mismatch returns HTTP 403. Missing, malformed, unknown, inactive, or revoked keys return HTTP 401.

Never place an API key in a URL Send it only in the X-API-Key request header over HTTPS. Do not include it in query strings, logs, screenshots, CSV files, or x402 payment payloads.

x402 Protocol Headers

HeaderDirectionPurpose
PAYMENT-REQUIREDMerchant → agentBase64-encoded x402 v2 payment challenge returned with HTTP 402.
PAYMENT-SIGNATUREAgent → merchantBase64-encoded x402 v2 payment payload containing the selected terms and proof.
PAYMENT-RESPONSEMerchant → agentBase64-encoded x402 v2 settlement response returned when the resource is released.
X-Agent-IDAgent → merchantOptional identity supplied when requesting the initial challenge.
X-Wallet-AddressAgent → merchantOptional public wallet identity supplied when requesting the challenge.

Encoding

Protocol headers contain standard Base64 text created from UTF-8 JSON. The decoded JSON limit is 16,384 bytes. Invalid Base64, oversized content, or a payload that fails x402 v2 validation returns HTTP 400.

encoded_header = Base64(UTF8(canonical_json(protocol_object)))

Payment challenge shape

{ "x402Version": 2, "resource": { "url": "https://example.test/v1/x402/prototype/merchant_123/resources/weather-current", "description": "Deterministic Zahlen x402 test weather resource", "mimeType": "application/json" }, "accepts": [{ "scheme": "exact", "network": "local:zahlen-test", "amount": "80000", "asset": "ZTEST", "payTo": "<test-payment-destination>", "maxTimeoutSeconds": 300, "extra": {} }], "extensions": { "zahlen-observability": { "info": { "challengeId": "<challenge-id>", "correlationId": "<correlation-id>" }, "schema": {"type": "object"} } } }

Payment payload shape

{ "x402Version": 2, "resource": {"url": "<exact-resource-url-from-challenge>"}, "accepted": {"scheme": "exact", "network": "local:zahlen-test", "amount": "80000", "asset": "ZTEST", "payTo": "<same-payTo>", "maxTimeoutSeconds": 300, "extra": {}}, "payload": { "payer": "local:wallet_123", "agentId": "agent_123", "nonce": "unique-nonce", "proof": "<deterministic-test-proof>" }, "extensions": {"zahlen-observability": {"info": {"challengeId": "<same-challenge-id>"}, "schema": {"type": "object"}}} }

The accepted object must exactly match one challenge option. A nonce or proof must never be reused. Live provider payloads will be documented with their adapter when a live adapter is connected and approved.

Endpoint Summary

Protocol and merchant API routes

MethodPathAuthenticationResult
GET/v1/x402/prototype/{merchant_id}/resources/{resource_id}x402 headersIssue a challenge or process proof and return/withhold the resource.
GET/v1/x402/prototype/{merchant_id}/observability/{correlation_id}X-API-KeyReturn the immutable lifecycle timeline.
POST/v1/x402/prototype/{merchant_id}/reconciliation/{correlation_id}X-API-KeyAppend a new reconciliation assessment.
POST/v1/x402/prototype/{merchant_id}/policiesX-API-KeyAppend a versioned merchant policy.
GET/v1/x402/prototype/{merchant_id}/policies/effectiveX-API-KeyReturn the currently effective policy.
GET/v1/x402/prototype/{merchant_id}/visibilityX-API-KeyReturn merchant activity, policy, anomalies, reconciliation, and trends.
GET/v1/x402/prototype/{merchant_id}/visibility/identity-historyX-API-KeyReturn history for one agent, wallet, or both.
GET/v1/x402/prototype/{merchant_id}/visibility/audit-evidence/{correlation_id}.zipX-API-KeyDownload a verifiable audit ZIP.

Protected Resource Lifecycle

1. Request the resource

curl -i \ -H "X-Agent-ID: agent_123" \ -H "X-Wallet-Address: local:wallet_123" \ "https://zahlenfinancial.com/v1/x402/prototype/merchant_123/resources/weather-current"

When no payment proof is present, the response is HTTP 402. Its JSON body reports payment_required, deterministic test mode, and no monetary value. Decode the PAYMENT-REQUIRED response header to read the x402 v2 challenge.

2. Build and submit the proof

curl -i \ -H "PAYMENT-SIGNATURE: <base64-x402-v2-payment-payload>" \ "https://zahlenfinancial.com/v1/x402/prototype/merchant_123/resources/weather-current"

3. Interpret the result

  • HTTP 200: verification, policy, and test settlement succeeded; the resource body is returned with PAYMENT-RESPONSE.
  • HTTP 402 payment_denied: proof or policy failed and delivery was withheld.
  • HTTP 402 payment_review_required: the policy requires human or approved follow-up before delivery.
One proof, one use Resubmitting the same proof is recorded as replay evidence. Zahlen withholds the resource and does not create a second successful settlement.

Observability Timeline

GET /v1/x402/prototype/{merchant_id}/observability/{correlation_id} X-API-Key: <merchant-api-key>

The response contains the complete ordered record history for the correlation ID.

{ "merchantId": "merchant_123", "correlationId": "x402cor_...", "count": 8, "records": [ {"contract_version": "1.0", "record_type": "payment_resource_request", "...": "..."}, {"contract_version": "1.0", "record_type": "http_402_challenge", "...": "..."}, {"contract_version": "1.0", "record_type": "payment_authorization_proof", "...": "..."}, {"contract_version": "1.0", "record_type": "verification_result", "...": "..."}, {"contract_version": "1.0", "record_type": "policy_decision", "...": "..."}, {"contract_version": "1.0", "record_type": "settlement_result", "...": "..."}, {"contract_version": "1.0", "record_type": "resource_delivery_result", "...": "..."}, {"contract_version": "1.0", "record_type": "reconciliation_record", "...": "..."} ] }

A denied, failed, or replayed lifecycle can contain a different number of records because settlement or release may not occur.

Append a Reconciliation Assessment

curl -X POST \ -H "X-API-Key: <merchant-api-key>" \ "https://zahlenfinancial.com/v1/x402/prototype/merchant_123/reconciliation/x402cor_123"

A successful request returns HTTP 201 with a new reconciliation record. Earlier records stay unchanged. Repeating the assessment creates new evidence rather than overwriting the original result.

matchedPayment completed and the resource was released with no exceptions.
pendingThe lifecycle does not yet contain enough final evidence.
exceptionPayment and delivery do not match, proof repeated, verification failed, or settlement remains unresolved.
resolvedA later append-only record documents resolution of an earlier exception.

Versioned Policy Profiles

Policy profiles are append-only. Post a new policy version instead of editing an existing row. Zahlen assigns contract_version, profile_id, tenant_id, and merchant_id; clients must not send those fields.

Create a policy

POST /v1/x402/prototype/{merchant_id}/policies Content-Type: application/json X-API-Key: <merchant-api-key>
{ "policy_version": "merchant-risk-2026-08-26", "known_agent_ids": ["agent_123"], "known_wallet_addresses": ["local:wallet_123"], "known_bindings": [{"agent_id": "agent_123", "wallet_address": "local:wallet_123"}], "unknown_agent_action": "review", "unknown_wallet_action": "review", "authorized_resource_ids": ["weather-current"], "authorized_endpoint_origins": ["https://zahlenfinancial.com"], "authorized_endpoint_paths": ["/v1/x402/prototype/merchant_123/resources/weather-current"], "authorized_methods": ["GET"], "spend_limits": [{ "asset": "ZTEST", "network": "local:zahlen-test", "per_request_amount": "1000000", "daily_amount": "10000000", "rolling_amount": "3000000", "rolling_window_seconds": 3600 }], "velocity_window_seconds": 60, "max_attempts_per_velocity_window": 10, "allowed_assets": ["ZTEST"], "allowed_networks": ["local:zahlen-test"], "allowed_facilitator_ids": ["zahlen-local-test-facilitator-v1"], "require_active_merchant": true, "require_healthy_service": true, "anomaly_review_threshold": 25, "anomaly_deny_threshold": 70 }

Amounts are strings containing non-negative atomic units, not floating-point numbers. Required lists cannot be empty or contain duplicates. The review threshold must be lower than the deny threshold.

Read the effective policy

GET /v1/x402/prototype/{merchant_id}/policies/effective X-API-Key: <merchant-api-key>

The response is {"profile": {...}}. HTTP 404 means no policy is currently effective for that merchant.

Merchant Visibility APIs

Dashboard visibility

GET /v1/x402/prototype/{merchant_id}/visibility?window_hours=24&limit=100 X-API-Key: <merchant-api-key>
Query parameterRulesMeaning
window_hours1–720; default 24How far back to read immutable records.
limit1–500; default 100Maximum result rows per dashboard collection.
agent_idOptional; 1–255 charactersFilter activity to one agent identity.
wallet_addressOptional; 1–2,048 charactersFilter activity to one public wallet identity.

The response contains:

  • scope and selected time-window information.
  • summary counts and settled amounts by asset.
  • transactions with payment, policy, settlement, delivery, and reconciliation states.
  • identities for agent and wallet history.
  • policyDecisions with reason codes and anomaly scores.
  • anomaliesAndReplays for unusual or repeated activity.
  • settlementAndDelivery and reconciliationExceptions.
  • trends with time buckets and attempts per hour.
  • dataQuality showing immutable x402 ledgers as the source.

Identity history

GET /v1/x402/prototype/{merchant_id}/visibility/identity-history?agent_id=agent_123&window_hours=720 X-API-Key: <merchant-api-key>

Supply agent_id, wallet_address, or both. Omitting both returns HTTP 422. The maximum activity window is 720 hours and the maximum limit is 500.

Downloadable Audit Evidence

GET /v1/x402/prototype/{merchant_id}/visibility/audit-evidence/{correlation_id}.zip X-API-Key: <merchant-api-key>

The response is an application/zip download with these headers:

  • Cache-Control: no-store
  • X-Zahlen-Evidence-Fingerprint
  • X-Zahlen-Evidence-Record-Count
  • Content-Disposition with the generated filename

The ZIP contains:

manifest.jsonArtifact identity, scope, record count, and fingerprints.
records.jsonCanonical append-only records and individual record fingerprints.
activity.csvA review-friendly lifecycle summary.
Verify downloaded evidence Compare the response fingerprint with the manifest and retain the original ZIP unchanged when it supports an investigation, reconciliation case, or audit.

Operator Dashboard APIs

These routes support the Zahlen browser dashboard. They use an authenticated browser session and tenant security context. They are not replacements for merchant-key API integration.

MethodPathPurpose
GET/admin/x402Render the x402 Merchant Dashboard.
GET/admin/x402/dataReturn tenant-scoped dashboard JSON. Requires merchant_id.
GET/admin/x402/uploads/template.csvReturn an example ZIP without a merchant, or a merchant-bound CSV template.
POST/admin/x402/uploads/previewValidate a multipart CSV without saving rows.
POST/admin/x402/uploads/commitAppend valid rows after fingerprint-verified preview.
GET/admin/x402/audit-evidence/{correlation_id}.zipDownload tenant-scoped evidence from the dashboard.

CSV preview

Content-Type: multipart/form-data X-Zahlen-Requested-With: x402-dashboard merchant_id=<merchant-id or blank only for the example flow> file=<UTF-8 CSV; maximum 2 MB and 1,000 rows>

CSV commit

Submit the same file and merchant scope, plus the exact 71-character expected_fingerprint returned by preview. A changed file returns HTTP 409 and must be previewed again.

The dashboard write header is required Preview and commit reject requests that do not include X-Zahlen-Requested-With: x402-dashboard.

Canonical Schema and Data Rules

Zahlen records lifecycle evidence using contract version 1.0. Every record answers who attempted to pay, what they requested, under which authorization, what happened, whether it was expected, and what should happen next.

IdentityAgent IDs and wallet addresses are identity and audit data, never credentials.
TimeTimestamps are timezone-aware ISO 8601 values.
AmountsAtomic-unit strings prevent floating-point rounding errors.
FingerprintsEvidence fingerprints use sha256: followed by 64 lowercase hexadecimal characters.
CorrectionsCorrections and later outcomes are new records; existing records are not overwritten.
VersioningBreaking contract changes require a new version rather than silent field changes.

Canonical record types

  • payment_resource_request
  • http_402_challenge
  • payment_authorization_proof
  • verification_result
  • policy_decision
  • settlement_result
  • resource_delivery_result
  • replay_duplicate_attempt
  • reconciliation_record

HTTP Status and Error Guide

StatusMeaningDeveloper action
200Read succeeded or paid resource released.Process the body and, for resource delivery, retain PAYMENT-RESPONSE.
201Policy or reconciliation record appended.Store returned IDs and version information.
400Malformed, oversized, or invalid PAYMENT-SIGNATURE.Rebuild the Base64 x402 v2 payload from the current challenge.
401Merchant API key missing, malformed, invalid, inactive, or revoked.Send a current key in X-API-Key.
402Payment required, denied, or held for review.Read the body, reason code, policy decision, and challenge header.
403Merchant or tenant scope mismatch, or required dashboard write header missing.Use credentials and identifiers from the same merchant scope.
404Prototype disabled, merchant/resource absent, evidence absent, or no effective policy.Confirm environment, flag, scope, resource ID, and correlation ID.
409Append conflict or CSV changed after preview.Do not overwrite evidence; refresh or preview the current file again.
413CSV file exceeds 2 MB.Split or reduce the file.
422Request, policy, filter, or CSV validation failed.Correct the fields using the returned detail or row reason codes.

Facilitator failures are normalized into safe reason codes such as facilitator_verify_timeout and facilitator_settle_timeout. Delivery is withheld when verification or settlement cannot be trusted.

Security Requirements

  • Use HTTPS for all non-local requests.
  • Never send or store private keys, seed phrases, mnemonics, signing secrets, passwords, bearer tokens, or unrelated credentials in x402 payloads.
  • Treat wallet addresses, public transaction identifiers, public signatures, and agent IDs as identities and audit data.
  • Keep merchant API keys server-side and rotate or revoke them under your normal access policy.
  • Never reuse a nonce or payment proof.
  • Do not release a resource based only on the presence of a proof; require verification and the policy result.
  • Respect Review as a hold state, not an approval.
  • Use correlation IDs rather than payment secrets when requesting support.
  • Retain audit ZIPs according to your organization's evidence and privacy rules.
Zahlen never stores private keys A field that appears to contain private-key or credential material is rejected by the x402 contract. Zahlen is not a wallet custodian or signing service.

Integration Checklist

  1. Use a local or approved development environment with the prototype flag enabled.
  2. Create or select an active merchant and obtain a merchant-scoped API key.
  3. Request weather-current and decode the PAYMENT-REQUIRED header.
  4. Build a unique deterministic test proof using the exact accepted terms.
  5. Submit the proof and confirm HTTP 200 plus PAYMENT-RESPONSE.
  6. Read the correlation timeline and confirm expected record types.
  7. Post and read a versioned policy profile.
  8. Test Allow, Deny, Review, invalid proof, replay, timeout, and unavailable-facilitator paths.
  9. Review visibility, identity history, reconciliation exceptions, and trends.
  10. Download an audit bundle and verify its manifest fingerprint.
  11. Confirm that card-payment regression tests and x402 tests remain green.
  12. Keep live payments disabled until the Coinbase adapter, merchant terms, credentials, and rollout evidence pass the separate production-hardening review.
Definition of test integration success The same correlation ID connects the challenge, proof, verification, policy decision, settlement, delivery, reconciliation, visibility response, and downloadable evidence.