openapi: 3.1.0
info:
  title: RpcNode Public API
  version: '1.0'
  description: |
    Signed merchant HTTPS JSON API for plan/usage, JSON-RPC endpoint management,
    Address Watch, and payment webhooks (paid + included AML).

    JSON-RPC traffic itself goes to each endpoint URL
    (`https://{network}-{env}.rpcnode.dev/{uuid}`), not through this host.

    Docs: https://docs.rpcnode.dev/public-api/overview
    Agent brief: https://rpcnode.dev/llms.txt
  contact:
    email: admin@rpcnode.dev
    url: https://rpcnode.dev
servers:
  - url: https://api.rpcnode.dev
    description: Production (paths start at /v1, no /api prefix)

security:
  - hmacHeaders: []

tags:
  - name: Account
  - name: Endpoints
  - name: AddressWatch

paths:
  /v1/account:
    get:
      tags: [Account]
      summary: Current plan and usage snapshot
      operationId: getAccount
      responses:
        '200':
          description: Plan + usage
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AccountResponse'

  /v1/account/usage:
    get:
      tags: [Account]
      summary: Usage series
      operationId: getAccountUsage
      parameters:
        - in: query
          name: days
          schema:
            type: integer
            default: 30
      responses:
        '200':
          description: Daily series
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UsageSeriesResponse'

  /v1/endpoints:
    get:
      tags: [Endpoints]
      summary: List JSON-RPC endpoints
      operationId: listEndpoints
      responses:
        '200':
          description: Endpoint list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EndpointListResponse'
    post:
      tags: [Endpoints]
      summary: Create a JSON-RPC endpoint
      operationId: createEndpoint
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [network_slug, env_slug]
              properties:
                network_slug:
                  type: string
                  example: ethereum
                env_slug:
                  type: string
                  example: mainnet
                name:
                  type: string
      responses:
        '200':
          description: Created endpoint
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EndpointResponse'

  /v1/endpoints/{id}:
    get:
      tags: [Endpoints]
      summary: Get one endpoint
      operationId: getEndpoint
      parameters:
        - $ref: '#/components/parameters/EndpointId'
      responses:
        '200':
          description: Endpoint
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EndpointResponse'

  /v1/address-watch/account:
    get:
      tags: [AddressWatch]
      summary: Slots and webhook flags
      operationId: getAddressWatchAccount
      responses:
        '200':
          description: Address Watch account
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OkObject'

  /v1/address-watch/addresses:
    get:
      tags: [AddressWatch]
      summary: List watched addresses
      operationId: listWatchedAddresses
      parameters:
        - in: query
          name: network_slug
          schema:
            type: string
        - in: query
          name: address
          schema:
            type: string
        - in: query
          name: page
          schema:
            type: integer
            default: 1
        - in: query
          name: per_page
          schema:
            type: integer
            default: 50
      responses:
        '200':
          description: Paginated addresses
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OkObject'
    post:
      tags: [AddressWatch]
      summary: Watch an address
      operationId: addWatchedAddress
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [network_slug, address]
              properties:
                network_slug:
                  type: string
                  example: ethereum
                address:
                  type: string
                  example: '0x0000000000000000000000000000000000000000'
      responses:
        '200':
          description: Created watch
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OkObject'

  /v1/address-watch/events:
    get:
      tags: [AddressWatch]
      summary: List watch events
      operationId: listWatchEvents
      responses:
        '200':
          description: Events
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OkObject'

  /v1/address-watch/webhook:
    get:
      tags: [AddressWatch]
      summary: Current webhook URL and filters
      operationId: getWatchWebhook
      responses:
        '200':
          description: Webhook config + egress IPs
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OkObject'
    put:
      tags: [AddressWatch]
      summary: Set webhook URL and event filters
      operationId: putWatchWebhook
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [url, enabled]
              properties:
                url:
                  type: string
                  format: uri
                enabled:
                  type: boolean
                events:
                  type: object
                  description: Optional filters (payment / payout / block + network lists)
      responses:
        '200':
          description: Updated webhook
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OkObject'

components:
  securitySchemes:
    hmacHeaders:
      type: apiKey
      in: header
      name: X-Api-Key
      description: |
        Also send X-Timestamp (unix seconds) and X-Signature.
        signature = hex(HMAC-SHA256(secret, timestamp + "\n" + METHOD + "\n" + path + "\n" + sha256Hex(body))).
        Sign the path without the query string. Empty body hashes as SHA-256 of "".
        See https://docs.rpcnode.dev/public-api/authentication

  parameters:
    EndpointId:
      in: path
      name: id
      required: true
      schema:
        type: integer

  schemas:
    OkObject:
      type: object
      additionalProperties: true
      properties:
        ok:
          type: boolean
          example: true
        error:
          type: string

    AccountResponse:
      type: object
      properties:
        ok:
          type: boolean
        user_id:
          type: integer
        plan:
          type: object
          nullable: true
          properties:
            id: { type: integer }
            slug: { type: string }
            name: { type: string }
            included_credits: { type: integer }
            rps_limit: { type: integer }
            endpoints_limit: { type: integer }
            webhook_address_slots: { type: integer }
        usage:
          type: object
          additionalProperties: true

    UsageSeriesResponse:
      type: object
      additionalProperties: true
      properties:
        ok:
          type: boolean

    Endpoint:
      type: object
      properties:
        id: { type: integer }
        uuid: { type: string, format: uuid }
        name: { type: string }
        status: { type: string, enum: [active, paused] }
        network_slug: { type: string }
        env_slug: { type: string }
        url:
          type: string
          example: https://ethereum-mainnet.rpcnode.dev/a1b2c3d4-e5f6-7890-abcd-ef1234567890
        rps_limit: { type: integer }
        allowed_ips:
          type: array
          items: { type: string }

    EndpointResponse:
      type: object
      properties:
        ok: { type: boolean }
        endpoint:
          $ref: '#/components/schemas/Endpoint'

    EndpointListResponse:
      type: object
      properties:
        ok: { type: boolean }
        items:
          type: array
          items:
            $ref: '#/components/schemas/Endpoint'
