{
  "openapi": "3.1.0",
  "info": {
    "title": "Aere Cloud API",
    "version": "1.0.0",
    "description": "Keyed JSON-RPC, post-quantum signature verification via chain-native precompiles, and chain data for Aere Network (chain 2800). Authentication is an API key whose keccak-256 hash lives in the on-chain AereCloudSubscriptionsV2 contract at 0xfA2375F5c30d25e0b952F5Ac07Bc292aD3C20433; the gateway validates every key against the chain and fails closed. WebSocket subscriptions (outside this REST spec) live at wss://cloud.aere.network/v1/ws with the same key, via x-api-key header or ?key= query. Human docs: https://aere.network/cloud-docs.html",
    "contact": {
      "email": "office@aere.network",
      "url": "https://aere.network/cloud.html"
    }
  },
  "servers": [
    {
      "url": "https://cloud.aere.network/v1"
    }
  ],
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Format: ak2800.<0x address>.<secret>. Register keccak256 of the whole key string on-chain via AereCloudSubscriptionsV2.subscribe (free trial, or self-serve at listing), or have it granted by sales for invoice-paid plans."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "hint": {
            "type": "string"
          }
        },
        "required": [
          "error"
        ]
      },
      "Anchor": {
        "type": "object",
        "description": "A post-quantum anchor block: heights satisfy height % 32 == 16, from 13014000.",
        "properties": {
          "height": {
            "type": "integer"
          },
          "hash": {
            "type": "string"
          },
          "timestamp": {
            "type": "integer"
          },
          "falconSeals": {
            "type": "integer",
            "description": "count of Falcon-512 validator seals carried by this anchor"
          },
          "certificateDigest": {
            "type": [
              "string",
              "null"
            ],
            "description": "32-byte certificate digest from extraData vanity, covered by the block hash"
          }
        }
      },
      "JsonRpcRequest": {
        "type": "object",
        "properties": {
          "jsonrpc": {
            "const": "2.0"
          },
          "id": {},
          "method": {
            "type": "string"
          },
          "params": {
            "type": "array"
          }
        },
        "required": [
          "jsonrpc",
          "method"
        ]
      }
    },
    "responses": {
      "e401": {
        "description": "Missing API key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "e403": {
        "description": "Invalid or expired key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "e429": {
        "description": "Over the plan's per-second limit; Retry-After: 1",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "e503": {
        "description": "Subscription could not be verified on-chain; the gateway fails closed",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  },
  "security": [
    {
      "apiKey": []
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "summary": "Liveness and chain head; the only unauthenticated route",
        "security": [],
        "responses": {
          "200": {
            "description": "Gateway and node are healthy",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "chainId": {
                      "const": 2800
                    },
                    "block": {
                      "type": "integer"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "chainId": 2800,
                  "block": 15220078
                }
              }
            }
          }
        }
      }
    },
    "/rpc": {
      "post": {
        "summary": "JSON-RPC 2.0 on chain 2800 (single or batch)",
        "description": "Allowed: eth_*, net_*, web3_*, qbft_getValidatorsByBlockNumber, qbft_getValidatorsByBlockHash, qbft_getSignerMetrics, qbft_getPendingVotes. Anything else answers a JSON-RPC error -32601 in place, preserving batch positions.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/JsonRpcRequest"
                  },
                  {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/JsonRpcRequest"
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC response from the node"
          },
          "401": {
            "$ref": "#/components/responses/e401"
          },
          "403": {
            "$ref": "#/components/responses/e403"
          },
          "429": {
            "$ref": "#/components/responses/e429"
          },
          "503": {
            "$ref": "#/components/responses/e503"
          }
        }
      }
    },
    "/pq/verify": {
      "post": {
        "summary": "Verify a NIST post-quantum signature via the chain's native precompiles",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "scheme": {
                    "enum": [
                      "ml-dsa-44",
                      "slh-dsa-128s",
                      "falcon-512",
                      "falcon-1024"
                    ]
                  },
                  "publicKey": {
                    "type": "string",
                    "description": "0x-prefixed hex"
                  },
                  "signature": {
                    "type": "string",
                    "description": "0x hex; ml-dsa-44 and slh-dsa-128s only"
                  },
                  "message": {
                    "type": "string",
                    "description": "0x hex; ml-dsa-44 and slh-dsa-128s only"
                  },
                  "signedMessage": {
                    "type": "string",
                    "description": "0x hex Falcon reference signed-message blob; falcon-512 and falcon-1024 only"
                  }
                },
                "required": [
                  "scheme",
                  "publicKey"
                ]
              },
              "example": {
                "scheme": "ml-dsa-44",
                "publicKey": "0x\u2026",
                "signature": "0x\u2026",
                "message": "0x\u2026"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Verdict computed on-chain",
            "content": {
              "application/json": {
                "example": {
                  "valid": true,
                  "scheme": "ml-dsa-44",
                  "precompile": "0x0000000000000000000000000000000000000ae3",
                  "block": 15220111,
                  "chainId": 2800
                }
              }
            }
          },
          "400": {
            "description": "Malformed input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/e401"
          },
          "403": {
            "$ref": "#/components/responses/e403"
          },
          "429": {
            "$ref": "#/components/responses/e429"
          },
          "503": {
            "$ref": "#/components/responses/e503"
          }
        }
      }
    },
    "/account": {
      "get": {
        "summary": "Your subscription and usage over the last 31 days",
        "responses": {
          "200": {
            "description": "Account state",
            "content": {
              "application/json": {
                "example": {
                  "address": "0xbeb3\u20266465",
                  "planId": 0,
                  "plan": {
                    "name": "rpc-build",
                    "monthlyPriceWei": "980000000000000000000",
                    "active": true
                  },
                  "expiresAt": 1790065218,
                  "expiresAtIso": "2026-09-22T08:20:18.000Z",
                  "usageLast31Days": {
                    "rpc": 1204,
                    "pq": 37,
                    "data": 12
                  },
                  "contract": "0xfa2375f5c30d25e0b952f5ac07bc292ad3c20433",
                  "chainId": 2800
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/e401"
          },
          "403": {
            "$ref": "#/components/responses/e403"
          }
        }
      }
    },
    "/data/head": {
      "get": {
        "summary": "Chain head with timestamp and base fee",
        "responses": {
          "200": {
            "description": "Head",
            "content": {
              "application/json": {
                "example": {
                  "chainId": 2800,
                  "block": 15225986,
                  "hash": "0x6539\u2026a3b0",
                  "timestamp": 1787477821,
                  "baseFeeWei": "1000000000"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/e401"
          }
        }
      }
    },
    "/data/validators": {
      "get": {
        "summary": "The live QBFT validator set, read from consensus",
        "responses": {
          "200": {
            "description": "Validator set",
            "content": {
              "application/json": {
                "example": {
                  "chainId": 2800,
                  "count": 9,
                  "validators": [
                    "0x1bd5\u2026",
                    "0x4bf6\u2026"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/e401"
          }
        }
      }
    },
    "/data/anchors": {
      "get": {
        "summary": "Latest post-quantum anchor certificates, newest first",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Anchors",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "chainId": {
                      "const": 2800
                    },
                    "head": {
                      "type": "integer"
                    },
                    "anchorIntervalBlocks": {
                      "const": 32
                    },
                    "firstAnchorBlock": {
                      "const": 13014000
                    },
                    "anchors": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Anchor"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/e401"
          }
        }
      }
    },
    "/data/anchors/{height}": {
      "get": {
        "summary": "One anchor by height (height % 32 == 16, height >= 13014000)",
        "parameters": [
          {
            "name": "height",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The anchor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Anchor"
                }
              }
            }
          },
          "400": {
            "description": "Not an anchor height",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Block not found"
          },
          "401": {
            "$ref": "#/components/responses/e401"
          }
        }
      }
    },
    "/webhooks": {
      "get": {
        "summary": "List your webhooks (secrets masked)",
        "responses": {
          "200": {
            "description": "Webhook list"
          },
          "401": {
            "$ref": "#/components/responses/e401"
          }
        }
      },
      "post": {
        "summary": "Create a webhook (max 5 per account; public http(s) targets only)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "type": {
                    "enum": [
                      "pq-anchors",
                      "subscription-events",
                      "address-activity"
                    ]
                  },
                  "url": {
                    "type": "string"
                  },
                  "address": {
                    "type": "string",
                    "description": "watched 0x address; address-activity only"
                  }
                },
                "required": [
                  "type",
                  "url"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created; the HMAC secret is returned once"
          },
          "400": {
            "description": "Bad type/url/address, or private target refused"
          },
          "409": {
            "description": "Webhook limit reached"
          },
          "401": {
            "$ref": "#/components/responses/e401"
          }
        }
      }
    },
    "/webhooks/{id}": {
      "delete": {
        "summary": "Delete one of your webhooks",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted"
          },
          "404": {
            "description": "Not yours or not found"
          },
          "401": {
            "$ref": "#/components/responses/e401"
          }
        }
      }
    },
    "/notarize": {
      "post": {
        "summary": "Notarize a 32-byte digest on-chain (we pay the gas); first-seen is immutable",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "hash": {
                    "type": "string",
                    "description": "0x + 64 hex chars"
                  }
                },
                "required": [
                  "hash"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Receipt with txHash, block, firstSeenAt, firstTime"
          },
          "400": {
            "description": "Malformed hash"
          },
          "401": {
            "$ref": "#/components/responses/e401"
          },
          "503": {
            "description": "Notary temporarily unavailable"
          }
        }
      }
    },
    "/notarize/{hash}": {
      "get": {
        "summary": "Read the on-chain proof for a digest",
        "parameters": [
          {
            "name": "hash",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "notarized flag with firstSeenAt/firstSeenIso"
          },
          "401": {
            "$ref": "#/components/responses/e401"
          }
        }
      }
    },
    "/data/transfers": {
      "get": {
        "summary": "Transfers touching an address: token from genesis, native from launch (boundaries in the response)",
        "parameters": [
          {
            "name": "address",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "tokenTransfers + nativeTransfers with tokenHistoryComplete and nativeSince"
          },
          "400": {
            "description": "Missing or malformed address"
          },
          "401": {
            "$ref": "#/components/responses/e401"
          }
        }
      }
    },
    "/sponsor/createAccount": {
      "post": {
        "summary": "Deploy a user's passkey smart account; the Foundation relayer pays the gas (metered per API key)",
        "responses": {
          "200": {
            "description": "Account deployed"
          },
          "400": {
            "description": "Relayer validation error"
          },
          "401": {
            "$ref": "#/components/responses/e401"
          },
          "503": {
            "description": "Relayer unavailable"
          }
        }
      }
    },
    "/sponsor/execute": {
      "post": {
        "summary": "Submit a user's signed operation via the sponsoring relayer",
        "responses": {
          "200": {
            "description": "Submitted"
          },
          "400": {
            "description": "Relayer validation error"
          },
          "401": {
            "$ref": "#/components/responses/e401"
          },
          "503": {
            "description": "Relayer unavailable"
          }
        }
      }
    },
    "/sponsor/health": {
      "get": {
        "summary": "Relayer liveness and gas balance",
        "responses": {
          "200": {
            "description": "ok with balance_aere"
          },
          "401": {
            "$ref": "#/components/responses/e401"
          }
        }
      }
    }
  }
}