EventEdge Oracle Recurring payments API

Signed once by the customer, charged by your renewal job.

Operations 8

POST /v1/allowances/restore/resolve Read an allowance-restore session back #
POST /v1/allowances/restore/session Session for restoring the allowance one subscription needs #
POST /v1/charges Execute one recurring charge #
POST /v1/charges/recover Find the transaction that charged one recurring period #
POST /v1/subscriptions Create subscription terms and a setup token #
POST /v1/subscriptions/finalize Exchange a signature for a charge capability #
POST /v1/subscriptions/resolve Authoritative terms plus the EIP-712 payload to sign #
POST /v1/subscriptions/status Current state, read from the chain #

Documentation

Specifications

Other Resources

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/eventedge-oracle-recurring-payments-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

eventedge-oracle-recurring-payments-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: P2Flux Recurring payments API
  version: 1.0.0
  summary: Non-custodial USDC payments, subscriptions and refunds on Base.
  description: Programmable, non-custodial payments on Base.
  contact:
    name: P2Flux
    url: https://p2flux.com/docs/
  license:
    name: Documentation for the hosted P2Flux API
    url: https://p2flux.com/terms.html
servers:
- url: https://api.p2flux.com
  description: 'Production - Base Mainnet (8453). Real money: every settlement moves real USDC and cannot be reversed by P2Flux. Point your integration here; use the test server for experiments.'
- url: https://api-test.p2flux.com
  description: Test - Base Sepolia (84532). Identical API against the test deployment; value moved here is faucet USDC, not real money. The interactive explorer is restricted to this server by design.
security: []
tags:
- name: Recurring Payments
  description: Signed once by the customer, charged by your renewal job.
paths:
  /v1/allowances/restore/resolve:
    post:
      operationId: resolveAllowanceRestore
      summary: Read an allowance-restore session back
      tags:
      - Recurring Payments
      description: 'For the browser holding the session: the terms of the approval to ask for. Terms only - the transaction is the customer''s own standard ERC-20 `approve()`, which their wallet builds and sends.


        The spender is P2Flux''s recurring contract, taken from the signed session. A screen that accepted a spender from its own input would be a phishing page.'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              required:
              - approve_token
              properties:
                approve_token:
                  $ref: '#/components/schemas/Token'
                gas_payment_mode:
                  type: string
                  enum:
                  - native
                  - payment_token
                  default: native
                  description: With `payment_token` the response also carries a price and the two messages the customer signs, and P2Flux sends the transaction. Without it the response describes the customer's own `approve()`, as before.
                allowance_units:
                  type: string
                  enum:
                  - '0'
                  description: 'Only `"0"` is accepted, and it prices a REMOVAL of the allowance instead of a restore. The quote returned is bound to that operation: a removal quote is refused on a restore submit and vice versa. Absent means "restore what this subscription needs".'
      responses:
        '200':
          description: What to approve, and who must approve it.
          content:
            application/json:
              schema:
                type: object
                properties:
                  chain_id:
                    type: integer
                  token:
                    $ref: '#/components/schemas/Address'
                  spender:
                    $ref: '#/components/schemas/Address'
                  payer:
                    $ref: '#/components/schemas/Address'
                  subscription_id:
                    $ref: '#/components/schemas/Bytes32'
                  required_units:
                    $ref: '#/components/schemas/AmountUnits'
                    description: The signed amount plus the gas reimbursement the next charge may add. An allowance covering only the amount stalls on the reimbursement.
                  expires_at:
                    type: integer
                  approve_units:
                    type:
                    - string
                    - 'null'
                    description: What to approve, in base units; null means unlimited. The subscription's own setup mode, so a bounded allowance is not widened on repair.
        '400':
          description: 'Refused. `error` names which of: `INVALID_CANCEL_TOKEN`, `CANCEL_TOKEN_EXPIRED`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Rate limited per IP.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /v1/allowances/restore/session:
    post:
      operationId: createAllowanceRestoreSession
      summary: Session for restoring the allowance one subscription needs
      tags:
      - Recurring Payments
      description: '`INSUFFICIENT_ALLOWANCE` is not a dead subscription. The authorization the customer signed is intact and the seller can still collect; what ran short is the ERC-20 allowance, and the fix is one `approve()` from the customer''s own wallet - no new signature, no new subscription.


        This exchanges the capability for the narrowest browser-facing token P2Flux issues: the payer, the spender (the recurring contract), the token and how much the next charge will pull. It carries no authorization struct and no signature, so it cannot be turned into a capability, cannot build `revoke()` and cannot prepare a refund. Hand it to the customer at `/#/approve/`.


        Short-lived by design - it only has to survive the walk from your account page to a wallet confirmation.'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              required:
              - subscription
              properties:
                subscription:
                  $ref: '#/components/schemas/Token'
      responses:
        '200':
          description: The session, and who must send the approval.
          content:
            application/json:
              schema:
                type: object
                properties:
                  approve_token:
                    $ref: '#/components/schemas/Token'
                  expires_at:
                    type: integer
                    description: Unix seconds.
                  payer:
                    $ref: '#/components/schemas/Address'
                  subscription_id:
                    $ref: '#/components/schemas/Bytes32'
        '400':
          description: 'Refused. `error` names which of: `INVALID_SUBSCRIPTION`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Rate limited per IP.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /v1/charges:
    post:
      operationId: charge
      summary: Execute one recurring charge
      tags:
      - Recurring Payments
      description: 'Collect one billing period. Call it from your own renewal job - P2Flux schedules nothing.


        **Safe to retry.** The contract allows one charge per period, so a repeat call after a timeout or a crash returns `ALREADY_CHARGED` rather than charging again. Treat that as success.


        **`CONFIRMING` is not a failure.** The transaction is on chain and not yet settled: leave the period open, change nothing, and ask again in a few seconds about the same transaction. Its `action` is `WAIT`, and it is the one result that must never be shown to a customer as an error - they have paid.


        Every other outcome carries an `action` telling you what to do; the retry SCHEDULE (an hour, a day, a dunning email) is your business policy, not ours.'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              properties:
                subscription:
                  $ref: '#/components/schemas/Token'
              required:
              - subscription
      responses:
        '200':
          description: The charge outcome.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum:
                    - CHARGED
                    - ALREADY_CHARGED
                    - CONFIRMING
                  ok:
                    type: boolean
                    description: True for CHARGED and ALREADY_CHARGED - both mean the period is paid.
                  already_paid:
                    type: boolean
                  action:
                    $ref: '#/components/schemas/MerchantAction'
                  tx_hash:
                    $ref: '#/components/schemas/Bytes32'
                  subscription_id:
                    $ref: '#/components/schemas/Bytes32'
                  amount:
                    $ref: '#/components/schemas/Amount'
                  period_index:
                    type: integer
                  next_period_at:
                    type: string
              examples:
                charged:
                  summary: Collected
                  value:
                    status: CHARGED
                    ok: true
                    already_paid: false
                    action: SUCCESS
                    tx_hash: '0x3f63e790571cc0cc6e0e4efee1954e034022a949f0b120127bdd25beedca2371'
                    amount: '10.000000'
                    period_index: 0
                confirming:
                  summary: Sent, not settled - wait, never re-charge
                  value:
                    status: CONFIRMING
                    ok: false
                    already_paid: false
                    action: WAIT
                    tx_hash: '0x3f63e790571cc0cc6e0e4efee1954e034022a949f0b120127bdd25beedca2371'
                    period_index: 0
        '400':
          description: 'Refused. `error` names which of: `INVALID_SUBSCRIPTION`, `PERMISSION_REVOKED`, `INSUFFICIENT_BALANCE`, `INSUFFICIENT_ALLOWANCE`, `TRANSACTION_REVERTED`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: 'Refused. `error` names which of: `NOT_DUE`, `SUBSCRIPTION_EXPIRED`, `GAS_TOO_HIGH`, `PAYMENT_ALREADY_PROCESSED`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: 'Refused. `error` names which of: `RATE_LIMITED`, `CONCURRENCY_LIMIT`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '502':
          description: 'Refused. `error` names which of: `GAS_QUOTE_UNAVAILABLE`, `RELAYER_ERROR`, `RPC_ERROR`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '503':
          description: 'Operator-side limits, not payment outcomes: nothing was spent and the subscription is untouched. Retry later; a customer can do nothing about a gas spike.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /v1/charges/recover:
    post:
      operationId: recoverCharge
      summary: Find the transaction that charged one recurring period
      tags:
      - Recurring Payments
      description: 'For when a charge landed and its response did not: your retry answers `ALREADY_CHARGED`, which proves the period was collected and names no transaction. P2Flux stores nothing, so the hash lives only in the contract''s log - and without it you cannot attribute the payment to an order, audit it, or refund it, because refunds start from the original settlement.


        Give it the subscription and the exact period. There is no ''current period'' form on purpose: you are reconciling one specific collection, today or in a year, and the answer must not move under you.


        **The event is the proof.** A settlement is returned only when the contract''s own `SubscriptionCharged` log names this subscription AND this period, and only when its payer, recipient and amount match the signed authorization.


        **`found: false` is ordinary.** There is no catch-up billing, so a period that was never collected is a normal history: a later period having been charged says nothing about an earlier one. Like the one-time recovery, a miss is a statement about one block height and never a permanent verdict.


        A `hint` is an optimisation and nothing else - it narrows where the search starts, can never turn a miss into a hit, and is safe to omit.'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              required:
              - subscription
              - period_index
              properties:
                subscription:
                  $ref: '#/components/schemas/Token'
                period_index:
                  type: integer
                  minimum: 0
                  description: The exact billing period to reconcile, as returned by /v1/charges or /v1/subscriptions/status.
                hint:
                  type: object
                  additionalProperties: false
                  description: Where your own records say you attempted the charge. Narrows the search; never evidence.
                  properties:
                    attempted_at:
                      type: integer
                      minimum: 0
                      description: Unix seconds.
                    block:
                      type: integer
                      minimum: 0
      responses:
        '200':
          description: Either the located settlement, or a not-found that names the block it was true at.
          content:
            application/json:
              schema:
                type: object
                required:
                - found
                properties:
                  found:
                    type: boolean
                  subscription_id:
                    $ref: '#/components/schemas/Bytes32'
                  period_index:
                    type: integer
                  tx_hash:
                    $ref: '#/components/schemas/Bytes32'
                  block_number:
                    type: string
                  payer:
                    $ref: '#/components/schemas/Address'
                  recipient:
                    $ref: '#/components/schemas/Address'
                  net_units:
                    $ref: '#/components/schemas/AmountUnits'
                  fee_units:
                    $ref: '#/components/schemas/AmountUnits'
                  network_fee_units:
                    $ref: '#/components/schemas/AmountUnits'
                  amount_units:
                    $ref: '#/components/schemas/AmountUnits'
                    description: 'net + fee + networkFee: the amount the authorization signed for.'
                  code:
                    $ref: '#/components/schemas/ErrorCode'
                  as_of_block:
                    type: string
                    description: Only on a miss. The head this answer was computed at.
        '400':
          description: 'Refused. `error` names which of: `INVALID_SUBSCRIPTION`, `INVALID_REQUEST`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: '`PAYMENT_CONFIRMING` - the settlement exists and is not yet deep enough to act on. The transaction hash rides along; ask again about that same one.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Limited per IP and per subscription - reconciliation is a background job, not a poll loop.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '502':
          description: '`PAYMENT_RECOVERY_INCONSISTENT` (a log that contradicts the signed terms) or `RPC_ERROR`.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '503':
          description: '`RECOVERY_UNAVAILABLE` - the search could not be completed within its bounded budget on this deployment. Retryable.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /v1/subscriptions:
    post:
      operationId: createSubscription
      summary: Create subscription terms and a setup token
      tags:
      - Recurring Payments
      description: 'Terms for a recurring authorization the customer signs once. P2Flux has no scheduler and no database: your application owns the subscription lifecycle and decides when a renewal is due; the contract enforces one charge per period against the terms that were signed.'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              properties:
                recipient:
                  $ref: '#/components/schemas/Address'
                amount:
                  $ref: '#/components/schemas/Amount'
                period:
                  type: integer
                  description: Billing period in seconds. Minimum 3600 in production.
                end:
                  type: integer
                  minimum: 0
                  description: Unix seconds, or 0 for no end date.
                allowance:
                  description: 'How much ERC-20 allowance the hosted checkout asks the customer''s wallet for. ''unlimited'' (default: one approval, never asked again), ''until_end'' (enough for every period up to `end`; needs an end date), or {periods: N} for N charges'' worth (1..1200), after which your restore flow asks again. The mode is carried inside the setup token; a restore session keeps the same mode. Whatever the mode, the allowance only reaches the recurring contract, which moves nothing the signed authorization does not permit.'
                  oneOf:
                  - type: string
                    enum:
                    - unlimited
                    - until_end
                  - type: object
                    required:
                    - periods
                    additionalProperties: false
                    properties:
                      periods:
                        type: integer
                        minimum: 1
                        maximum: 1200
              required:
              - recipient
              - amount
              - period
      responses:
        '200':
          description: A setup token to hand to the checkout.
          content:
            application/json:
              schema:
                type: object
                properties:
                  setup_token:
                    $ref: '#/components/schemas/Token'
                  expires_at:
                    type: integer
                  chain_id:
                    type: integer
                  contract:
                    $ref: '#/components/schemas/Address'
                  amount:
                    $ref: '#/components/schemas/Amount'
                  salt:
                    type: string
        '400':
          description: A recurring charge carries a fixed network fee, so amounts below roughly 0.102041 USDC cannot leave the merchant anything and are refused.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /v1/subscriptions/finalize:
    post:
      operationId: finalizeSubscription
      summary: Exchange a signature for a charge capability
      tags:
      - Recurring Payments
      description: 'Validates the customer''s signature against the terms and returns the `p2s2` capability that charges this subscription. Contract wallets are supported (ERC-1271).


        **Store the capability.** It is bearer authorization bound to one subscription''s signed terms - keep it server-side, encrypted at rest, and never send it to a browser. Losing it means you cannot charge; leaking it means somebody else can, though only ever to the recipient the customer signed for.'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              properties:
                setup_token:
                  $ref: '#/components/schemas/Token'
                payer:
                  $ref: '#/components/schemas/Address'
                signature:
                  $ref: '#/components/schemas/Signature'
                sponsorship:
                  type: object
                  additionalProperties: false
                  required:
                  - quote
                  - permit_signature
                  - network_fee_signature
                  description: 'For a customer with no native currency: the two extra signatures from `resolve`. The capability is minted first - proving the authorization costs nothing - and then P2Flux sends one transaction that collects the quoted fee and sets the allowance. Absent for every integration that existed before this did.'
                  properties:
                    quote:
                      $ref: '#/components/schemas/Token'
                    permit_signature:
                      $ref: '#/components/schemas/Signature'
                    network_fee_signature:
                      $ref: '#/components/schemas/Signature'
                    permit_nonce:
                      type: string
                      description: What the wallet was told the token's permit counter was. Checked against the chain before anything is sent.
              required:
              - setup_token
              - payer
              - signature
      responses:
        '200':
          description: The capability and the subscription identity.
          content:
            application/json:
              schema:
                type: object
                properties:
                  subscription:
                    $ref: '#/components/schemas/Token'
                  subscription_id:
                    $ref: '#/components/schemas/Bytes32'
                  amount:
                    $ref: '#/components/schemas/Amount'
                  period:
                    type: integer
                  end:
                    type: integer
                  sponsorship:
                    type: object
                    description: 'Only when `sponsorship` was sent. The subscription exists regardless of this outcome: a sponsorship that fails leaves the capability valid and the allowance to be set from the restore flow or the customer''s own wallet. `ALREADY_SETTLED` is a repeat of a request whose allowance was set the first time - confirmed against the chain, because the token reports a spent authorization and one the customer cancelled with the same words, and only one of those means the setup is done. `FAILED` carries the `code` and its details.'
                    properties:
                      status:
                        type: string
                        enum:
                        - SETTLED
                        - SPONSORSHIP_CONFIRMING
                        - ALREADY_SETTLED
                        - FAILED
                      tx_hash:
                        type: string
                      network_fee_units:
                        type: string
                      allowance_units:
                        type: string
                      block_number:
                        type: string
                      native_gas_spent_wei:
                        type: string
                      code:
                        $ref: '#/components/schemas/ErrorCode'
        '400':
          description: '`UNSUPPORTED_SIGNATURE_FORMAT`: an ERC-6492 wrapper - the account must be deployed first, because a recurring authorization is replayed for months. `SIGNATURE_VALIDATION_TOO_EXPENSIVE` is not a verdict that the signature is wrong; it means validating it cost more than we are willing to spend.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: '`RATE_LIMITED`: this payer has reached the day''s sponsored broadcasts (`SPONSORED_ATTEMPTS_PER_PAYER_24H`). `CONCURRENCY_LIMIT` with `cause: PAYER_UNRESOLVED`: a previous sponsored transaction of this payer is still unresolved on chain; retry after it settles. Only with `sponsorship`.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '502':
          description: 'Refused. `error` names which of: `RPC_ERROR`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '503':
          description: '`PAYMENT_TOKEN_GAS_UNAVAILABLE` with `cause: SPONSORSHIP_PAUSED` (the relayer''s own infrastructure has been failing and the mode is paused for everyone for up to an hour) or `cause: PAYER_REVERTS` (this wallet''s sponsored transactions reverted on chain today and it is refused sponsorship for a day). `RELAYER_NOT_READY`: the relayer cannot record the operation durably. Only with `sponsorship`; the native path is unaffected.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /v1/subscriptions/resolve:
    post:
      operationId: resolveSubscription
      summary: Authoritative terms plus the EIP-712 payload to sign
      tags:
      - Recurring Payments
      description: What the customer is agreeing to, stated by the server, together with the exact typed data their wallet will show them. `network_fee_estimate` is indicative and best-effort - it may be null if the chain could not be asked, and it is never what gets charged.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              properties:
                setup_token:
                  $ref: '#/components/schemas/Token'
                gas_payment_mode:
                  type: string
                  enum:
                  - native
                  - payment_token
                  description: Optional. `payment_token` with `payer` prices the allowance transaction P2Flux would send for a customer holding no native currency, and returns the two messages they sign. Absent means the customer approves from their own wallet, exactly as before.
                payer:
                  $ref: '#/components/schemas/Address'
                  description: 'Required with `gas_payment_mode: payment_token`: the permit is priced for, and signed by, this wallet.'
              required:
              - setup_token
      responses:
        '200':
          description: Terms and typed data.
          content:
            application/json:
              schema:
                type: object
                properties:
                  recipient:
                    $ref: '#/components/schemas/Address'
                  amount:
                    $ref: '#/components/schemas/Amount'
                  amount_units:
                    $ref: '#/components/schemas/AmountUnits'
                  period:
                    type: integer
                  start:
                    type: integer
                  end:
                    type: integer
                  token:
                    $ref: '#/components/schemas/Address'
                  chain_id:
                    type: integer
                  contract:
                    $ref: '#/components/schemas/Address'
                  salt:
                    type: string
                  max_gas_reimbursement:
                    $ref: '#/components/schemas/AmountUnits'
                  fee_bps:
                    type: integer
                  network_fee:
                    $ref: '#/components/schemas/Amount'
                  network_fee_units:
                    $ref: '#/components/schemas/AmountUnits'
                  network_fee_estimate:
                    type:
                    - string
                    - 'null'
                  expires_at:
                    type: integer
                  typed_data:
                    type: object
                    description: EIP-712 domain, types and primaryType.
                  allowance:
                    type: object
                    description: The allowance mode fixed at setup.
                    properties:
                      mode:
                        type: string
                        enum:
                        - unlimited
                        - until_end
                        - periods
                      periods:
                        type: integer
                    required:
                    - mode
                  approve_units:
                    type:
                    - string
                    - 'null'
                    description: What the checkout asks the wallet to approve, in base units. null means unlimited. Never below one charge (amount plus max_gas_reimbursement).
                  approve_amount:
                    type:
                    - string
                    - 'null'
                    description: approve_units as a decimal USDC string; null means unlimited.
                  gas_payment_mode:
                    type: string
                    enum:
                    - payment_token
                    description: Present only when the signup was priced for a customer with no native currency.
                  sponsorship_quote:
                    type: object
                    description: 'With `payment_token`: the quoted network fee, its expiry, and the `p2gas1` quote to hand back to `finalize`.'
                  allowance_permit:
                    type: object
                    description: 'With `payment_token`: the EIP-2612 permit the customer signs. Spender is the recurring contract; value is the subscription''s allowance mode.'
                  network_fee_authorization:
                    type: object
                    description: 'With `payment_token`: the token authorization for the quoted fee. Expires with the quote.'
        '400':
          description: 'Refused. `error` names which of: `INVALID_SETUP_TOKEN`, `SETUP_TOKEN_EXPIRED`, `AMOUNT_OUT_OF_BOUNDS`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /v1/subscriptions/status:
    post:
      operationId: subscriptionStatus
      summary: Current state, read from the chain
      tags:
      - Recurring Payments
      description: 'Everything about this subscription as the chain sees it. Use it to reconcile after downtime, and to decide whether a renewal is due without guessing from your own clock.


        The signed terms are echoed under `terms` - compare `terms.salt` against the setup you finalized if you need to be certain a capability belongs to the plan you think it does.'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              properties:
                subscription:
                  $ref: '#/components/schemas/Token'
              required:
              - subscription
      responses:
        '200':
          description: Chain-derived state.
          content:
            application/json:
              schema:
                type: object
                properties:
                  active:
                    type: boolean
                  revoked:
                    type: boolean
                  revoked_confirmed:
                    type: boolean
                    description: Revoked deeply enough to act on. `revoked` is read at the head; only this one is settled.
                  expired:
                    type: boolean
                  due:
                    type: boolean
                  charged_this_period:
                    type: boolean
                  subscription_id:
                    $ref: '#/components/schemas/Bytes32'


# --- truncated at 32 KB (38 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/eventedge-oracle/refs/heads/main/openapi/eventedge-oracle-recurring-payments-api-openapi.yml