REST API Reference

Hosted Base Sepolia API: https://cortex-api.projectaegis.ai

Local development API: http://localhost:3001 (configurable via API_PORT)

Authentication

Reads are public. Mutating routes can require X-Cortex-Api-Key when API_KEY_REQUIRED=true. Stateless compute routes such as /x402/normalize, /x402/verify, and /preflightremain public because they persist nothing.

Health Check

GET /health

{ "status": "ok" }

Catalog Documents

Publish Catalog JSON

POST /catalogs

Canonicalizes catalog JSON and stores the canonical bytes by keccak256 hash. Use the returned uri and catalog_hash as the service metadata URI/hash.

{
  "catalog_json": "{\n  \"merchant\": {...},\n  \"services\": [...]\n}",
  "expected_hash": "0x...",
  "merchant_id": "1",
  "service_id": "enrich-company-v1"
}
{
  "catalog_hash": "0x...",
  "merchant_id": "1",
  "service_id": "enrich-company-v1",
  "size_bytes": 2048,
  "uri": "https://cortex-api.projectaegis.ai/catalogs/0x...",
  "canonical_json": "{\"merchant\":{},\"services\":[]}"
}

Fetch Catalog JSON

GET /catalogs/:hash

Returns canonical JSON text as application/json. Metadata is available at GET /catalogs/:hash/metadata.


Quote Documents

Publish Quote Request

POST /quote-requests

Canonicalizes the agent quote request JSON by keccak256 hash and returns a stable URI.

{
  "quote_request_json": "{\n  \"request_id\": \"req-001\"\n}",
  "expected_hash": "0x...",
  "request_id": "req-001",
  "merchant_id": "1",
  "service_numeric_id": "1",
  "service_id": "enrich-company-v1",
  "agent": "0x..."
}

Publish Quote Response

POST /quote-responses

Canonicalizes the merchant quote response JSON and can link it to a hosted quote request hash.

{
  "quote_response_json": "{\n  \"request_id\": \"req-001\",\n  \"quote\": {...}\n}",
  "expected_hash": "0x...",
  "request_hash": "0x...",
  "request_id": "req-001",
  "merchant_id": "1",
  "service_numeric_id": "1",
  "agent": "0x..."
}

Fetch canonical JSON at GET /quote-requests/:hash and GET /quote-responses/:hash. Metadata is available at each route's /metadata path.

Publish License Document

POST /licenses

Canonicalizes a cortex.license.v1 document and returns the hash/URI agents use as license inventory.

{
  "license_json": "{\n  \"schema\": \"cortex.license.v1\",\n  \"issuer\": \"0x...\",\n  \"holder\": \"0x...\",\n  \"rights\": [\"read\", \"analyze\"]\n}",
  "expected_hash": "0x..."
}

Check License Use

POST /licenses/check

{
  "license_hash": "0x...",
  "agent": "0x...",
  "action": "commercial_output",
  "quote_hash": "0x...",
  "receipt_id": "1",
  "context": {
    "commercial": true,
    "model_training": false,
    "redistribution": false,
    "derivative": true
  }
}

Inventory is available at GET /licenses with filters for holder, issuer, merchant, service, asset, and active status.

Normalize x402 Payment Requirement

POST /x402/normalize

Normalizes a facilitator payment requirement into the Cortex canonical x402 shape, hashes it, and can compare the result against a quote's x402PayloadHash.

{
  "payment_requirement_json": {
    "accepts": [{
      "scheme": "exact",
      "network": "base-sepolia",
      "payTo": "0x...",
      "asset": "0x...",
      "maxAmountRequired": "1000000",
      "resource": "https://merchant.example/api/report",
      "method": "POST",
      "facilitator": { "url": "https://facilitator.example" },
      "nonce": "quote-001"
    }]
  },
  "expected_hash": "0x...",
  "quote": { "x402_payload_hash": "0x..." }
}
{
  "normalized": {
    "schema": "cortex.x402-payment-requirement.v1",
    "scheme": "exact",
    "network": "base-sepolia",
    "pay_to": "0x...",
    "asset": "0x...",
    "amount": "1000000"
  },
  "canonical_json": "{\"amount\":\"1000000\",\"asset\":\"0x...\"}",
  "x402_payload_hash": "0x...",
  "matches_expected_hash": true,
  "matches_quote_hash": true,
  "warnings": []
}

Agents should sign only after the normalized hash matches the quote-bound hash and policy checks pass.

Publish Encrypted Fulfillment Payload

POST /fulfillment-payloads

Stores canonical encrypted fulfillment payload envelopes by hash. Payloads should contain ciphertext and encryption metadata, not plaintext shipping data.

{
  "fulfillment_payload_json": "{\n  \"schema\": \"cortex.encrypted-fulfillment.v1\",\n  \"ciphertext\": \"base64:...\"\n}",
  "expected_hash": "0x...",
  "merchant_id": "1",
  "agent": "0x...",
  "quote_hash": "0x...",
  "encryption": "x25519-xsalsa20-poly1305",
  "merchant_key_id": "did:key:z6MkMerchantFulfillmentKey"
}

Fetch canonical envelope JSON at GET /fulfillment-payloads/:hash. Metadata is available at GET /fulfillment-payloads/:hash/metadata.


Agents

Get Agent by ID

GET /agents/:agentId

{
  "agent_id": "1",
  "owner": "0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc",
  "metadata_uri": "ipfs://agent-meta",
  "pubkey": "0xaabb",
  "capabilities_hash": "0x...",
  "revoked": false,
  "block_number": "10"
}

Errors: 400 (invalid ID), 404 (not found)

List Agents by Owner

GET /agents?owner=0x...&limit=50&offset=0

The owner parameter is required.

{
  "agents": [...],
  "pagination": { "limit": 50, "offset": 0, "count": 1 }
}

Intents

Get Intent by ID

GET /intents/:id

{
  "intent_id": "1",
  "owner": "0x...",
  "intent_type": "SWAP_EXACT_IN_MAX_SLIPPAGE",
  "input_token": "0x...",
  "output_token": "0x...",
  "amount_in_max": "1000000000000000000000",
  "amount_out_min": "900000000000000000000",
  "deadline": "1738965600",
  "slippage_bps": "100",
  "nonce": "42",
  "status": "FILLED",
  "block_number": "15",
  "fill": {
    "solver": "0x...",
    "amount_in": "950000000000000000000",
    "amount_out": "900000000000000000000",
    "tx_hash": "0x...",
    "block_number": "18"
  }
}

If the intent is not filled, fill is null.

List Intents

GET /intents?status=open&limit=50&offset=0

The status filter is optional. Valid values: open, filled, cancelled.

{
  "intents": [...],
  "pagination": { "limit": 50, "offset": 0, "count": 5 }
}

Policies

Get Account Policies

GET /accounts/:address/policies?limit=50&offset=0

{
  "account": "0x...",
  "policies": [
    {
      "policy_type": "SPEND_LIMIT",
      "token": "0x1111111111111111111111111111111111111111",
      "max_per_day": "10000000000000000000000",
      "block_number": "12"
    },
    {
      "policy_type": "TARGET_ALLOWLIST",
      "target": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512",
      "allowed": true,
      "block_number": "13"
    }
  ],
  "pagination": { "limit": 50, "offset": 0, "count": 2 }
}

Commerce

GET /merchants?owner=0x...&active=true — list registered merchants.

GET /merchants/:id — get one merchant.

GET /services?merchant_id=1&capability_hash=0x...&active=true — list services.

GET /services/:id — get one service.

GET /facilitators?active=true — list payment facilitators.

GET /quotes/:quoteHash — get a canonical quote commitment.

GET /receipts?agent=0x...&merchant_id=1 — list settled receipts.

GET /disputes?receipt_id=1 — list receipt-linked disputes.

GET /trust-signals?subject_type=0&subject_id=1 — list trust and risk signals.

GET /merchants/:id/reputation — get receipt, fulfillment, dispute, and trust summaries.

{
  "quote_hash": "0x...",
  "merchant_id": "1",
  "service_numeric_id": "1",
  "agent": "0x...",
  "token": "0x...",
  "facilitator": "0x...",
  "amount": "1000000000000000000",
  "payment_rail": 3,
  "protocol_fee_bps": 0,
  "protocol_fee_amount": "0",
  "payment_nonce": "1",
  "resource_hash": "0x...",
  "terms_hash": "0x...",
  "x402_payload_hash": "0x...",
  "settled": true
}

Cortex supports basic wallet transfers, swaps, facilitator-mediated payments, and x402. The x402 payload hash is used only when the selected payment rail is x402.

Commerce Analytics

GET /analytics/commerce

{
  "summary": {
    "merchants": "1",
    "services": "1",
    "quotes": "1",
    "receipts": "1",
    "settled_volume": "1000000000000000000",
    "settled_protocol_fees": "0",
    "open_disputes": "0"
  },
  "volume_by_token": [],
  "top_merchants": [],
  "top_services": [],
  "facilitator_volume": [],
  "volume_by_payment_rail": [],
  "trust_signals_by_kind": []
}

Transaction Explain

Explain Transaction

GET /tx/:hash/explain

{
  "tx_hash": "0x...",
  "block_number": "15",
  "summary": "Transaction contained 1 event(s)",
  "events": [
    {
      "eventName": "IntentSubmitted",
      "args": { "intentId": "1", "owner": "0x...", "nonce": "42" },
      "description": "Intent #1 submitted by 0x..."
    }
  ]
}

Common Parameters

ParameterDefaultMaxDescription
limit50100Results per page
offset0Results to skip

Notes

  • All addresses are normalized to lowercase.
  • NUMERIC/BIGINT values are returned as strings for BigInt safety.
  • All error responses follow the format { "error": "message" }.