> ## Documentation Index
> Fetch the complete documentation index at: https://nevermined.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Call a Service with Subscription Credits

> Call a catalog service and pay it with your Nevermined Subscription credits (mode B). Like `POST /router/route`, but Nevermined pays the merchant from its treasury and your subscription is charged the endpoint's rate in credits. There is no Delegation, no wallet to fund and no routing fee.

- **A slug, never a URL.** Address the service by `slug` (+ `path`, `search`, `method`, `headers`, `body`). A `url` or a `delegationId` is refused (`BCK.SUBSCRIPTION_ROUTER.0005`), not ignored.
- **`requestId` is required** (idempotency): a retry with the same id is never paid twice.
- **Only a merchant `2xx` keeps the credits.** They are reserved before the merchant is called and kept (`Committed`) only on a `2xx`; anything else marks them for refund and they are returned (`Refunded`). Every refusal below happens before anything is reserved, signed or charged — except a 502, which can follow a payment.
- **Rails:** x402 `exact` and MPP `tempo` merchants only.

For large or streamed responses, the streaming form is `ALL /api/v1/router/subscription/svc/{slug}/{path}` with an `X-Router-Request-Id` header; it answers with `X-Router-Credits-Charged` and `X-Router-Credits-Status` beside the `X-Router-Payment-*` headers, and refuses `X-Router-Target-Url`, `X-Router-Target-Slug` and `X-Router-Delegation-Id`.

Personal API keys only: the Nevermined Subscription belongs to a personal account, so call with a key that carries no organization tag and without `X-Current-Org-Id`. An OAuth-minted credential is refused (`BCK.OAUTH.0030`). Where the subscription is not available — on this deployment or to this account — it answers 404 `BCK.SUBSCRIPTION_ACCESS.0001`.



## OpenAPI

````yaml POST /router/subscription/route
openapi: 3.1.0
info:
  title: Nevermined API
  description: >-
    API for managing AI agents, payment plans, and x402 payments in the
    Nevermined ecosystem.


    ## Prerequisites


    You need a Nevermined API Key to authenticate. Get one at
    [nevermined.app](https://nevermined.app) under **Settings > API Keys**.


    See the [5-Minute Setup Guide](/docs/integrate/quickstart/5-minute-setup)
    for detailed instructions.
  license:
    name: MIT
  version: 1.0.0
servers:
  - url: https://api.sandbox.nevermined.app/api/v1
    description: Sandbox (Testing) - Base Sepolia
  - url: https://api.live.nevermined.app/api/v1
    description: Live (Production) - Base Mainnet
security:
  - bearerAuth: []
tags:
  - name: Protocol - Agents
    description: Endpoints for registering and managing AI agents
  - name: Protocol - Plans
    description: Endpoints for creating and managing payment plans
  - name: Protocol - Credits
    description: Endpoints for minting and redeeming credits
  - name: Protocol - Access
    description: Endpoints for access tokens and request validation
  - name: X402 - Permissions
    description: Endpoints for x402 delegated permissions
paths:
  /router/subscription/route:
    post:
      tags:
        - Router
      summary: Call a catalog service, paid with subscription credits
      description: >-
        Call a catalog service and pay it with your Nevermined Subscription
        credits (mode B). Like `POST /router/route`, but Nevermined pays the
        merchant from its treasury and your subscription is charged the
        endpoint's rate in credits. There is no Delegation, no wallet to fund
        and no routing fee.


        - **A slug, never a URL.** Address the service by `slug` (+ `path`,
        `search`, `method`, `headers`, `body`). A `url` or a `delegationId` is
        refused (`BCK.SUBSCRIPTION_ROUTER.0005`), not ignored.

        - **`requestId` is required** (idempotency): a retry with the same id is
        never paid twice.

        - **Only a merchant `2xx` keeps the credits.** They are reserved before
        the merchant is called and kept (`Committed`) only on a `2xx`; anything
        else marks them for refund and they are returned (`Refunded`). Every
        refusal below happens before anything is reserved, signed or charged —
        except a 502, which can follow a payment.

        - **Rails:** x402 `exact` and MPP `tempo` merchants only.


        For large or streamed responses, the streaming form is `ALL
        /api/v1/router/subscription/svc/{slug}/{path}` with an
        `X-Router-Request-Id` header; it answers with `X-Router-Credits-Charged`
        and `X-Router-Credits-Status` beside the `X-Router-Payment-*` headers,
        and refuses `X-Router-Target-Url`, `X-Router-Target-Slug` and
        `X-Router-Delegation-Id`.


        Personal API keys only: the Nevermined Subscription belongs to a
        personal account, so call with a key that carries no organization tag
        and without `X-Current-Org-Id`. An OAuth-minted credential is refused
        (`BCK.OAUTH.0030`). Where the subscription is not available — on this
        deployment or to this account — it answers 404
        `BCK.SUBSCRIPTION_ACCESS.0001`.
      operationId: routeSubscriptionCall
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriptionRouteRequestDto'
            examples:
              pay-with-credits:
                summary: Call a catalog endpoint, paid with credits
                value:
                  slug: webscrape-pro
                  path: scrape
                  method: POST
                  body:
                    url: https://example.com
                  requestId: scrape-example-com-1
      responses:
        '201':
          description: >-
            The merchant's response (`status`, and `body` only when it
            delivered) plus the `payment` Nevermined made and the credits it
            cost.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionRouteResultDto'
        '202':
          description: >-
            API version 1.48 or later: the paid call outlived the synchronous
            wait. Poll `GET /api/v1/router/payments/{id}/result` (also the
            `Location` header); the credits stay `Reserved` until the call ends.
            A retry with the same `requestId` returns this same answer, then the
            result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoutePendingDto'
        '400':
          description: >-
            Invalid request; a field a subscription call does not accept
            (BCK.SUBSCRIPTION_ROUTER.0005, `params.field`); the merchant asked
            for a rail credits do not pay (BCK.SUBSCRIPTION_ROUTER.0003,
            `params.rail`); or the payment credential would overwrite a header
            you forward, with no `credentialHeader` naming where the service
            wants it (BCK.ROUTER.0021).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RouterErrorResponseDto'
        '401':
          description: Missing/invalid Nevermined API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RouterErrorResponseDto'
        '402':
          description: >-
            No subscription that can spend right now, including a call made in
            an organization you are an active member of (`X-Current-Org-Id`, or
            that organization's API key), which never falls back to your
            personal subscription (BCK.SUBSCRIPTION_ROUTER.0002); or not enough
            credits for this call (BCK.SUBSCRIPTION_ROUTER.0009,
            `params.credits`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RouterErrorResponseDto'
        '403':
          description: >-
            This endpoint cannot be paid with subscription credits
            (BCK.SUBSCRIPTION_ROUTER.0001, `params.reason`); the treasury cannot
            pay this merchant (BCK.SUBSCRIPTION_TREASURY.0008); or an
            OAuth-minted credential (BCK.OAUTH.0030).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RouterErrorResponseDto'
        '404':
          description: >-
            Not available to the caller (BCK.SUBSCRIPTION_ACCESS.0001), or no
            listed catalog service has that `slug` (BCK.CATALOG.0001).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RouterErrorResponseDto'
        '409':
          description: >-
            The merchant's live price is outside the rate's bound, in another
            asset or network, or could not be read as a price
            (BCK.SUBSCRIPTION_ROUTER.0004, `params.reason`); or the `requestId`
            was already used (BCK.ROUTER.0002 — from API 1.48, a retry of a
            finished call is answered from its retained result instead).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RouterErrorResponseDto'
        '413':
          description: >-
            The request body is larger than this endpoint accepts
            (BCK.ROUTER.0027, its `maxRequestBytes`) or than the Router accepts
            (BCK.ROUTER.0024). Refused before the service is contacted; nothing
            was charged.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RouterErrorResponseDto'
        '422':
          description: >-
            The merchant asked to be paid in an asset Nevermined's treasury does
            not pay in (BCK.SUBSCRIPTION_TREASURY.0002), or the endpoint is
            known to outlast the Router's paid-call limit (BCK.ROUTER.0036).
            Nothing was charged; pay this endpoint from a delegation, or pick
            another.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RouterErrorResponseDto'
        '429':
          description: >-
            The per-slug throttle or the per-user concurrency limit. A
            subscription has no spending limit beyond its credits.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RouterErrorResponseDto'
        '500':
          description: >-
            Nevermined-side error, nothing charged: the payment could not be
            prepared consistently (BCK.SUBSCRIPTION_ROUTER.0006, retryable with
            a new requestId), the subscription does not resolve to its credits
            (0011), the rate is unusable (0013), or a treasury configuration or
            ledger error (BCK.SUBSCRIPTION_TREASURY.0011–0013).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RouterErrorResponseDto'
        '502':
          description: >-
            The paid call got no response from the service (BCK.ROUTER.0034), or
            its reply was too large to deliver (BCK.ROUTER.0025): the merchant
            may have been paid, and the call's credits are marked for refund. Do
            not retry with a new `requestId`; read the outcome from `GET
            /api/v1/router/payments?requestId=…` (`creditsStatus`). An unpaid
            probe the service failed to answer (BCK.ROUTER.0020) paid nothing.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RouterErrorResponseDto'
        '503':
          description: >-
            Temporarily unable to pay, nothing charged: the reservation timed
            out (BCK.SUBSCRIPTION_ROUTER.0014, retry with the same requestId),
            the subscription lookup failed (0012), the deployment cannot run
            subscription calls (0010), or the treasury refused (a
            `BCK.SUBSCRIPTION_TREASURY.*` code, e.g. 0003 when its float cannot
            cover the payment). `retryable` says whether retrying can help.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RouterErrorResponseDto'
components:
  schemas:
    SubscriptionRouteRequestDto:
      type: object
      properties:
        slug:
          type: string
          description: >-
            Catalog slug of the service to call. Subscription credits pay
            catalog services only, addressed by slug; the Router resolves it to
            the merchant server-side.
          example: webscrape-pro
          pattern: ^[A-Za-z0-9._~-]+$
        path:
          type: string
          maxLength: 2048
          description: >-
            Subpath of the endpoint, appended to the resolved merchant URL (path
            segments only — `//`, `..`, a backslash or an embedded absolute URL
            is refused).
          example: scrape
        search:
          type: string
          maxLength: 2048
          description: >-
            Query string without the leading `?`, attached to the resolved
            merchant URL.
          example: q=nevermined&limit=1
        method:
          type: string
          description: HTTP method to use for the upstream request.
          enum:
            - GET
            - POST
            - PUT
            - PATCH
            - DELETE
          default: GET
        headers:
          type: object
          additionalProperties:
            type: string
          description: Headers to forward to the merchant (e.g. its own auth). Optional.
        body:
          description: Request body to forward (JSON). Optional.
        credentialHeader:
          type: string
          maxLength: 64
          description: >-
            Header the payment credential rides in on the paid hop, when the
            merchant needs its own `Authorization` too (a separate `Payment`
            header is the common one). Do not set it by default.
          example: Payment
        protocol:
          type: string
          enum:
            - x402
            - mpp
          default: x402
          description: 'Advisory: the Router detects the protocol from the merchant''s 402.'
        requestId:
          type: string
          description: >-
            Idempotency key — REQUIRED. At most one payment per (caller,
            requestId): a retry is never paid twice.
          maxLength: 256
          pattern: \S
          example: scrape-example-com-1
      required:
        - slug
        - requestId
    SubscriptionRouteResultDto:
      type: object
      properties:
        status:
          type: number
          description: The merchant's HTTP status.
        body:
          description: >-
            The merchant's response body — `null` unless a paid call delivered
            (2xx), so a failed call reveals nothing about the merchant. A free
            answer relays only its `status` (`paid: false`), except a declared
            follow-up poll after a paid call.
        bodyEncoding:
          type: string
          enum:
            - json
            - text
            - base64
          description: How `body` is represented. Absent when `body` is withheld.
        contentType:
          type:
            - string
            - 'null'
          description: The merchant's response media type, when `body` is relayed.
          example: application/json
        paid:
          type: boolean
          description: Whether a payment was made (false when the service answered free).
        payment:
          $ref: '#/components/schemas/SubscriptionRoutePaymentDto'
      required:
        - status
        - body
        - paid
    RoutePendingDto:
      type: object
      description: >-
        `202` answer of the `/route` family when the paid call outlives the 45 s
        sync budget: the payment was made, the call is still running on the
        Router, and its result will be readable at `resultUrl`.
      properties:
        paymentId:
          type: string
          example: b1f9c2e4-3d5a-4c7e-9f21-6a8b0c4d2e13
        resultUrl:
          type: string
          description: >-
            Read the result here with the same API key. Relative to the API
            host.
          example: /api/v1/router/payments/b1f9c2e4-3d5a-4c7e-9f21-6a8b0c4d2e13/result
        status:
          type: string
          enum:
            - Pending
          example: Pending
      required:
        - paymentId
        - resultUrl
        - status
    RouterErrorResponseDto:
      type: object
      properties:
        code:
          type: string
          description: >-
            Router error code. `BCK.ROUTER.0001` invalid request / no fundable
            option / bad 402 (400); `BCK.ROUTER.0002` requestId already used —
            idempotency conflict (409); `BCK.ROUTER.0003` delegation budget
            exceeded, expired, or inactive (402); `BCK.ROUTER.0004` payment
            record not found (404); `BCK.ROUTER.0005` payment not in a
            settleable state (409). Framework-level `BCK.HTTP.*` codes (e.g.
            `BCK.HTTP.400` request validation, `BCK.HTTP.429` throttling) may
            also appear — see the base `code` field.
          example: BCK.ROUTER.0003
        httpStatus:
          type: number
          description: HTTP status code
          example: 500
        message:
          type: string
          description: Error message for Router operations.
          example: delegation budget exceeded, expired, or inactive
          examples:
            - >-
              delegationId is required — create one via POST
              /api/v1/delegation/create
            - 'no fundable option; offered: [...]'
            - >-
              upstream pay-to address is not in this delegation's allowed
              recipients
            - delegation budget exceeded, expired, or inactive
            - payment already settled with a different txHash
        details:
          type: string
          description: >-
            Throw-site detail string supplementing the canonical message. Only
            set when the call site supplied an opts.message; absent otherwise.
          example: Hash JWT is not signed by the node account
        error:
          type: string
          description: >-
            RFC 6749 §5.2 / RFC 8628 §3.5 top-level OAuth error string. Present
            only on the OAuth device-polling responses from `POST /oauth/token`
            (`authorization_pending`, `slow_down`, `expired_token`,
            `access_denied`), so a standards-compliant OAuth/device client can
            branch on it directly instead of on the Nevermined `code`. Absent on
            every other error.
          example: authorization_pending
        hint:
          type: string
          description: >-
            Actionable remediation hint, sourced from the catalogue or supplied
            at the throw site. Tells the caller what to fix or where to look.
          example: >-
            Verify the wallet has sufficient balance and that the plan is
            active.
        docsUrl:
          type: string
          description: Permalink to the docs page describing this error code.
          example: >-
            https://nevermined.ai/docs/development-guide/api-errors/codes#bck-x402-0008
        category:
          type: string
          description: >-
            Coarse classification of the failure, useful for client-side
            branching without parsing the message.
          enum:
            - validation
            - auth
            - business
            - integration
            - internal
          example: integration
        retryable:
          type: boolean
          description: >-
            Whether the failure is transient and the same call can be retried
            with identical inputs. Absent when the catalogue does not assert
            either way.
          example: true
        correlationId:
          type: string
          description: >-
            Request-scoped correlation id stamped by the global filter. Echoed
            in the x-correlation-id response header. Quote this when reporting
            issues.
          example: a3f6b1c4-7d2e-4a9b-8e0c-12f4d8e6c5b9
        uuid:
          type: string
          description: >-
            Per-error UUID generated at construction. Useful for log
            correlation.
          example: e-550e8400-e29b-41d4-a716-446655440000
        date:
          type: string
          description: ISO timestamp at which the error was constructed.
          example: '2026-05-09T12:34:56.789Z'
          format: date-time
        params:
          type: string
          description: >-
            JSON-stringified contextual parameters supplied at the throw site
            (e.g. IDs, state). Always a string in the wire format — parse with
            JSON.parse if needed.
          example: '{"planId":"43298432984329","reason":"Invalid configuration"}'
      required:
        - code
        - httpStatus
        - message
    SubscriptionRoutePaymentDto:
      type: object
      properties:
        paymentId:
          type: string
          description: The Router payment id.
        status:
          type: string
          enum:
            - Issued
            - Settled
            - Failed
          description: The merchant leg, which Nevermined paid on your behalf.
        txHash:
          type:
            - string
            - 'null'
          description: >-
            On-chain settlement reference of the merchant leg, when the merchant
            returned one.
        creditsCharged:
          type: integer
          description: >-
            Credits this call cost (the endpoint's rate). Absent only when the
            ledger could not be read at answer time; `GET /router/payments` has
            it.
          example: 3
        creditsStatus:
          type: string
          enum:
            - Reserved
            - Committed
            - Refunded
          description: >-
            `Committed` — the merchant delivered (2xx) and the credits stay
            spent. `Reserved` — the call did not deliver and its credits are
            marked for refund, or its outcome is still being decided. `Refunded`
            — returned. Absent only when the ledger could not be read at answer
            time.
        failureReason:
          type:
            - string
            - 'null'
          description: Why the call did not complete cleanly, when it did not.
        correlationId:
          type:
            - string
            - 'null'
          description: The request correlation id.
        resultUrl:
          type: string
          description: Where this result stays readable for 24 h.
      required:
        - paymentId
        - status
        - txHash
        - failureReason
        - correlationId
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Your Nevermined API Key (starts with 'nvm:'). Get one at
        [nevermined.app](https://nevermined.app) under **Settings > API Keys**.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.