Skip to content

API Reference

Base URL: http://<host>:<port>/api/v1

All request and response bodies are JSON. Successful responses are wrapped in a data envelope:

json
{ "data": { ... } }

Errors return a consistent structure:

json
{
  "code": "ERROR_CODE",
  "message": "Human-readable message",
  "details": "Optional extra detail"
}

Authentication Headers

HeaderUsed byDescription
Authorization: Bearer <token>User JWT endpointsAccess token obtained from /login or /token/refresh.
X-Client-ID/verify, /settle, /supportedClient ID from POST /clients.
X-Client-Token/verify, /settle, /supportedClient token from POST /clients.

Health

GET /health

Returns server liveness. No authentication required.

Response 200

json
{
  "status": "healthy",
  "timestamp": 1712345678,
  "version": "1.0.0"
}

System

GET /api/v1/status

Returns detailed system status including database health and supported networks.

Response 200

json
{
  "data": {
    "status": "healthy",
    "version": "1.0.0",
    "uptime": 86400,
    "networks": [
      {
        "x402Version": 1,
        "scheme": "exact",
        "network": "base-sepolia",
        "status": "active",
        "block": 0,
        "feePayer": "0xYourAddress"
      }
    ],
    "database": {
      "status": "healthy"
    }
  }
}

Networks

GET /api/v1/networks

List all enabled networks. No authentication required.

Response 200

json
{
  "kinds": [
    {
      "x402Version": 1,
      "scheme": "exact",
      "network": "base-sepolia",
      "status": "active",
      "block": 0,
      "feePayer": "0xYourAddress"
    }
  ]
}

GET /api/v1/networks/:id

Get a single network by its network_name.

Path params

ParamDescription
idNetwork name (e.g. base-sepolia).

Response 200

json
{
  "x402Version": 1,
  "scheme": "exact",
  "network": "base-sepolia",
  "status": "active",
  "block": 0,
  "feePayer": "0xYourAddress",
  "extra": {
    "feePayer": "0xYourAddress"
  }
}

Response 400 - unknown network

json
{ "code": "INVALID_REQUEST", "message": "unsupported network", "details": "" }

Assets

GET /api/v1/assets

List all registered, active assets. No authentication required.

Response 200

json
{
  "data": [
    {
      "id": 1,
      "network": "base-sepolia",
      "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
      "symbol": "USDC",
      "decimals": 6,
      "active": true
    }
  ]
}

x402 - Core Endpoints

These endpoints require client API key authentication (X-Client-ID + X-Client-Token).

POST /api/v1/verify

Verify that a payment payload is valid against the given requirements. Does not settle on-chain.

Request

json
{
  "paymentPayload": {
    "x402Version": 1,
    "scheme": "exact",
    "network": "base-sepolia",
    "payload": "<base64-encoded-signed-data>"
  },
  "paymentRequirements": {
    "scheme": "exact",
    "network": "base-sepolia",
    "maxAmountRequired": "1000000",
    "resource": "/api/protected",
    "description": "Access to protected endpoint",
    "mimeType": "application/json",
    "payTo": "0xMerchantAddress",
    "maxTimeoutSeconds": 60,
    "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
    "x402Version": 1
  }
}
FieldTypeDescription
paymentPayloadobjectThe payer's signed payment object.
paymentPayload.x402VersionnumberProtocol version. Must be 1.
paymentPayload.schemestringPayment scheme ("exact").
paymentPayload.networkstringNetwork identifier.
paymentPayload.payloadstring | objectBase64-encoded signed payload, or a JSON object (auto-encoded server-side).
paymentRequirementsobjectThe requirements originally returned by the resource server.

Response 200 - valid

json
{
  "isValid": true,
  "invalidReason": "",
  "payer": "0xPayerAddress",
  "timestamp": 1712345678,
  "cachedResult": false
}

Response 200 - invalid (bad signature, wrong amount, expired, etc.)

json
{
  "isValid": false,
  "invalidReason": "signature mismatch",
  "payer": "",
  "timestamp": 1712345678,
  "cachedResult": false
}

Response 400 - malformed request

json
{ "code": "INVALID_REQUEST", "message": "Invalid request format", "details": "..." }

Response 500 - verification error

json
{ "code": "VERIFICATION_FAILED", "message": "Payment verification failed", "details": "..." }

POST /api/v1/settle

Verify and settle a payment on-chain. Broadcasts the transaction and returns the tx hash.

Call /verify first if you want to check validity without incurring gas costs.

Request - same shape as /verify

json
{
  "x402Version": 1,
  "paymentPayload": {
    "x402Version": 1,
    "scheme": "exact",
    "network": "base-sepolia",
    "payload": "<base64-encoded-signed-data>"
  },
  "paymentRequirements": {
    "scheme": "exact",
    "network": "base-sepolia",
    "maxAmountRequired": "1000000",
    "resource": "/api/protected",
    "description": "Access to protected endpoint",
    "mimeType": "application/json",
    "payTo": "0xMerchantAddress",
    "maxTimeoutSeconds": 60,
    "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
    "x402Version": 1
  }
}

Response 200 - settled

json
{
  "success": true,
  "transaction": "0xabc123...",
  "errorReason": "",
  "network": "base-sepolia",
  "payer": "0xPayerAddress",
  "blockNumber": 12345678,
  "timestamp": "2025-04-07T12:00:00Z"
}

Response 200 - settlement failed

json
{
  "success": false,
  "transaction": "",
  "errorReason": "insufficient balance",
  "network": "base-sepolia",
  "payer": "",
  "blockNumber": 0,
  "timestamp": "2025-04-07T12:00:00Z"
}

Response 500 - settlement error

json
{ "code": "SETTLEMENT_FAILED", "message": "Payment settlement failed", "details": "..." }

GET /api/v1/supported

Returns the list of supported networks (same as /networks) but requires client auth. Useful for validating that a client key is active.

Response 200 - same as GET /api/v1/networks


Authentication

POST /api/v1/signup

Create a new user account.

Request

json
{
  "email": "user@example.com",
  "password": "StrongPassword123!"
}

Response 200

json
{
  "data": {
    "message": "Account created",
    "user": {
      "id": 1,
      "email": "user@example.com",
      "isAdmin": false,
      "createdAt": "2025-04-07T12:00:00Z"
    }
  }
}

POST /api/v1/login

Authenticate and receive JWT tokens.

Request

json
{
  "email": "user@example.com",
  "password": "StrongPassword123!"
}

Response 200

json
{
  "data": {
    "message": "Login successful",
    "access_token": "eyJ...",
    "refresh_token": "eyJ...",
    "id": 1
  }
}

Response 401 - bad credentials

json
{ "message": "Invalid email or password" }

POST /api/v1/token/refresh

Exchange a valid refresh token for a new access token.

Request

json
{
  "refresh_token": "eyJ..."
}

Response 200

json
{
  "data": {
    "access_token": "eyJ..."
  }
}

Response 401 - expired or invalid refresh token

json
{ "message": "invalid session token", "details": "..." }

Client API Keys

Requires Authorization: Bearer <access_token>.

POST /api/v1/clients

Create a new client API key pair.

Request

json
{
  "title": "my-resource-server",
  "scope": "verify,settle",
  "ttl_hours": 8760
}
FieldTypeRequiredDescription
titlestringYesHuman-readable name for this client.
scopestringNoComma-separated list of allowed operations.
ttl_hoursnumberNoKey expiry in hours. Omit for no expiry.

Response 200

json
{
  "data": {
    "client": {
      "clientId": "abc123",
      "token": "hmac-signed-token",
      "title": "my-resource-server",
      "scope": "verify,settle",
      "createdAt": "2025-04-07T12:00:00Z",
      "expiresAt": null
    }
  }
}

Important: Store the token securely - it is not stored in plaintext and cannot be retrieved after creation.


GET /api/v1/clients

List your client keys. Admins see all clients; regular users see only their own.

Query params

ParamDefaultDescription
offset0Pagination offset.
limit20Page size.

Response 200

json
{
  "data": [
    {
      "clientId": "abc123",
      "title": "my-resource-server",
      "scope": "verify,settle",
      "createdAt": "2025-04-07T12:00:00Z",
      "expiresAt": null
    }
  ]
}

DELETE /api/v1/clients/:id

Soft-delete (revoke) a client key.

Path params

ParamDescription
idclientId of the key to revoke.

Response 200

json
{
  "data": {
    "deleted": "abc123"
  }
}

Resources

Requires Authorization: Bearer <access_token>.

Resources are the protected URLs that merchants register. The facilitator uses this registry to look up accepted payment methods when a client queries a resource.

POST /api/v1/resources

Register a new protected resource.

Request

json
{
  "resource": "/api/premium-data",
  "type": "endpoint",
  "x402Version": 1,
  "accepts": [
    {
      "scheme": "exact",
      "network": "base-sepolia",
      "maxAmountRequired": "1000000",
      "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
      "payTo": "0xYourAddress"
    }
  ],
  "metadata": {}
}

Response 201

json
{ "data": { "status": "created" } }

GET /api/v1/users/resources

List resources belonging to the authenticated user.

Query params: offset (default 0), limit (default 100).

Response 200

json
{
  "data": {
    "resources": [ { ... } ],
    "offset": 0,
    "limit": 100
  }
}

GET /api/v1/resources

List all resources (public, no auth required).

Response 200 - same shape as /users/resources.


PUT /api/v1/resources/:id

Update an existing resource.

Path params: id - resource database ID.

Request - same shape as POST /api/v1/resources.

Response 200

json
{ "data": { "updated": 42 } }

Metrics

Requires Authorization: Bearer <access_token>.

GET /api/v1/metrics/daily

HTTP request metrics aggregated by day.

Query params

ParamDescription
fromStart date (ISO 8601).
toEnd date (ISO 8601).

GET /api/v1/metrics/monthly

HTTP request metrics aggregated by month.


GET /api/v1/metrics/summary

Aggregated totals across all time.


GET /api/v1/x402-metrics/daily

x402 settlement metrics (amounts, fees, networks) aggregated by day.


GET /api/v1/x402-metrics/monthly

x402 settlement metrics aggregated by month.


GET /api/v1/x402-metrics/summary

x402 settlement totals across all time.


Admin Endpoints

Requires Authorization: Bearer <admin_token> (static token from config.yaml).

Base path: /admin

POST /admin/users

Create a new user (admin-seeded accounts).

Request

json
{
  "email": "newuser@example.com",
  "password": "InitialPassword1!",
  "is_admin": false
}

GET /admin/users

List all users.


POST /admin/assets

Register a new asset (token) in the asset registry. Assets must be registered before they can be used in payment requirements.

Request

json
{
  "network": "base-sepolia",
  "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
  "symbol": "USDC",
  "decimals": 6,
  "active": true
}

Error Codes

CodeHTTP StatusMeaning
INVALID_REQUEST400Malformed JSON or missing required fields.
INVALID_PAYLOAD400The payment payload could not be decoded.
VERIFICATION_FAILED500x402 library returned an error during verification.
SETTLEMENT_FAILED500x402 library returned an error during settlement.
UNAUTHORIZED401Missing or invalid credentials.
INTERNAL_ERROR500Unexpected server error.

Released under the MIT License.