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

# Get a private report

> Read the full report of a finished release test. The token is the last path segment of `reportUrl`. The token is the only credential: anyone who has the link can read the report, so keep it out of logs and public CI output. Responses carry `noindex`, `no-store` and `no-referrer` headers.



## OpenAPI

````yaml /openapi.json get /v1/reports/{token}
openapi: 3.1.0
info:
  title: Selo API
  version: 1.0.0
  summary: CI for x402. It pays your endpoint before your users do.
  description: >-
    Selo is a release gate for paid x402 APIs on Algorand. You authorize your
    endpoint, run a free preflight, then pay Selo 1.00 USDC over x402. Only
    after that payment settles does Selo pay your endpoint as a real x402
    client, run five release checks and return a deterministic PASS, FAIL or
    INCONCLUSIVE verdict with an Ed25519-signed attestation.


    There are no API keys. Access to a target is granted per target by
    authorization; the only paid route is `POST /v1/release-test`, paid with
    x402. Bodies are JSON, at most 64 KiB.
  contact:
    name: Selo
    url: https://useselo.xyz
servers:
  - url: https://api.useselo.xyz
    description: Production, Algorand Mainnet
security: []
tags:
  - name: Authorizations
    description: Prove you control the target before Selo sends it anything.
  - name: Preflight
    description: Check for free that a target can be tested and is within budget.
  - name: Release tests
    description: The paid x402 route that runs the release checks.
  - name: Reports
    description: Private, token-addressed reports of finished release tests.
  - name: Attestation keys
    description: Public keys that verify signed verdicts.
  - name: Discovery
    description: Machine-readable descriptions of Selo.
  - name: Health
    description: Liveness.
paths:
  /v1/reports/{token}:
    get:
      tags:
        - Reports
      summary: Get a private report
      description: >-
        Read the full report of a finished release test. The token is the last
        path segment of `reportUrl`. The token is the only credential: anyone
        who has the link can read the report, so keep it out of logs and public
        CI output. Responses carry `noindex`, `no-store` and `no-referrer`
        headers.
      operationId: getReport
      parameters:
        - name: token
          in: path
          required: true
          description: 43-character report token from `reportUrl`.
          schema:
            type: string
            pattern: ^[A-Za-z0-9_-]{43}$
          example: <report token>
      responses:
        '200':
          description: >-
            The report. Example built from the fixed-v2 demo run; values in
            angle brackets are placeholders because the private report is not
            published.
          headers:
            X-Robots-Tag:
              description: '`noindex, nofollow`.'
              schema:
                type: string
              example: noindex, nofollow
            Cache-Control:
              description: '`private, no-store`.'
              schema:
                type: string
              example: private, no-store
            Referrer-Policy:
              description: '`no-referrer`.'
              schema:
                type: string
              example: no-referrer
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReleaseReport'
              example:
                jobId: job_51AZ2WJZ78RF1WZC316Q1K38GG
                project: <project from the authorization>
                target:
                  url: https://demo.useselo.xyz/v1/orders
                  method: POST
                testedAt: '2026-10-26T10:24:02.883Z'
                completedAt: '2026-10-26T10:24:12.218Z'
                seloVersion: 71080ad
                verdict: PASS
                inconclusiveReason: null
                checks:
                  - id: handshake
                    status: PASS
                    code: HANDSHAKE_VALID
                    blocking: true
                    summary: >-
                      Target issued a valid x402 v2 challenge with a supported
                      requirement for network
                      algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8= and
                      asset 31566704.
                    evidence:
                      - evd_B23GQN052SFAET2QME89MVYX5G
                  - id: paid_delivery
                    status: PASS
                    code: PAID_AND_DELIVERED
                    blocking: true
                    summary: >-
                      Downstream payment settled and target returned 200 with
                      transaction
                      QEUF5D33T4YHYP3KKIY2PGCYF55XXSUYKS5GXFBAVAZ4IEZOE3ZQ.
                    evidence:
                      - evd_6K2ASNC2G3JG43Q0XE0MSXJATM
                      - evd_PYNAQNMTD7KQJSJ0ZM6D618AK4
                  - id: response_contract
                    status: PASS
                    code: CONTRACT_MATCHED
                    blocking: true
                    summary: >-
                      Observed response matched the expected status 200 and
                      content type application/json.
                    evidence:
                      - evd_6K2ASNC2G3JG43Q0XE0MSXJATM
                      - evd_EKR9NXGB5HRGPQ4ZBN3WM914FW
                  - id: discovery_contract
                    status: PASS
                    code: DISCOVERY_CONSISTENT
                    blocking: true
                    summary: >-
                      Live challenge and catalog record agree on method, URL,
                      payment terms and carry usable metadata.
                    evidence:
                      - evd_TE2XZJB33D4CXHV2EMW84SS6BG
                  - id: retry_safety
                    status: PASS
                    code: PASS_REPLAY_REJECTED
                    blocking: true
                    summary: >-
                      Replaying the identical signed payment header was rejected
                      with status 402.
                    evidence:
                      - evd_7ZVACZFH5PNMZAQ5T82YZN7Z9R
                warnings: []
                failureCodes: []
                targetChallengeSha256: >-
                  39793a689d67cb18a7a59fca4a2d6211575e577bc2496accee3c93bd0ca2e7cc
                expected:
                  status: 200
                  contentType: application/json
                  jsonSchema:
                    type: object
                    required:
                      - orderId
                      - receiptId
                      - fulfilled
                    properties:
                      orderId:
                        type: string
                        pattern: ^ord_[0-9a-f]{24}$
                      receiptId:
                        type: string
                        pattern: ^rcpt_[0-9a-f]{24}$
                      fulfilled:
                        const: true
                observedResponse:
                  status: 200
                  contentType: application/json
                  bodySha256: <sha256 hex of the paid response body>
                  bodyBytes: <body size in bytes>
                  txId: QEUF5D33T4YHYP3KKIY2PGCYF55XXSUYKS5GXFBAVAZ4IEZOE3ZQ
                  requestedAt: <ISO 8601 time of the paid request>
                money:
                  inboundTxId: EPBEZR22SZ5LYKFM7UJYCSFG5IWNA6QYZ6XHUA6KGTTDDQQ5UIJA
                  downstreamSpendUsdc: '0.01'
                  unresolvedSpendUsdc: '0.00'
                  downstreamTxIds:
                    - QEUF5D33T4YHYP3KKIY2PGCYF55XXSUYKS5GXFBAVAZ4IEZOE3ZQ
                  payments:
                    - status: SETTLED
                      amountUsdc: '0.01'
                      txId: QEUF5D33T4YHYP3KKIY2PGCYF55XXSUYKS5GXFBAVAZ4IEZOE3ZQ
                      expectedTxId: QEUF5D33T4YHYP3KKIY2PGCYF55XXSUYKS5GXFBAVAZ4IEZOE3ZQ
                scenarios:
                  - check: handshake
                    operationId: job_51AZ2WJZ78RF1WZC316Q1K38GG:handshake
                    status: EVALUATED
                    attempts: <attempt count>
                    durationMs: <milliseconds>
                    failureCode: null
                  - check: paid_delivery
                    operationId: job_51AZ2WJZ78RF1WZC316Q1K38GG:paid_delivery
                    status: EVALUATED
                    attempts: <attempt count>
                    durationMs: <milliseconds>
                    failureCode: null
                  - check: response_contract
                    operationId: job_51AZ2WJZ78RF1WZC316Q1K38GG:response_contract
                    status: EVALUATED
                    attempts: <attempt count>
                    durationMs: <milliseconds>
                    failureCode: null
                  - check: discovery_contract
                    operationId: job_51AZ2WJZ78RF1WZC316Q1K38GG:discovery_contract
                    status: EVALUATED
                    attempts: <attempt count>
                    durationMs: <milliseconds>
                    failureCode: null
                  - check: retry_safety
                    operationId: job_51AZ2WJZ78RF1WZC316Q1K38GG:retry_safety
                    status: EVALUATED
                    attempts: <attempt count>
                    durationMs: <milliseconds>
                    failureCode: null
        '404':
          description: Unknown or malformed token, or the job has no written report.
          headers:
            X-Robots-Tag:
              description: '`noindex, nofollow`.'
              schema:
                type: string
              example: noindex, nofollow
            Cache-Control:
              description: '`private, no-store`.'
              schema:
                type: string
              example: private, no-store
            Referrer-Policy:
              description: '`no-referrer`.'
              schema:
                type: string
              example: no-referrer
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                error: NOT_FOUND
                message: Report not found
        '500':
          $ref: '#/components/responses/InternalError'
components:
  schemas:
    ReleaseReport:
      type: object
      description: The private report of a finished release test.
      required:
        - jobId
        - project
        - target
        - testedAt
        - completedAt
        - seloVersion
        - verdict
        - inconclusiveReason
        - checks
        - warnings
        - failureCodes
        - targetChallengeSha256
        - expected
        - observedResponse
        - money
        - scenarios
      properties:
        jobId:
          type: string
          pattern: ^job_[0-9A-HJKMNP-TV-Z]{26}$
        project:
          type: string
          description: Project name from the authorization.
        target:
          type: object
          required:
            - url
            - method
          properties:
            url:
              type: string
            method:
              $ref: '#/components/schemas/HttpMethod'
        testedAt:
          type:
            - string
            - 'null'
          format: date-time
        completedAt:
          type:
            - string
            - 'null'
          format: date-time
        seloVersion:
          type: string
        verdict:
          oneOf:
            - $ref: '#/components/schemas/Verdict'
            - type: 'null'
        inconclusiveReason:
          oneOf:
            - $ref: '#/components/schemas/InconclusiveReason'
            - type: 'null'
        checks:
          type: array
          items:
            $ref: '#/components/schemas/CheckResult'
        warnings:
          type: array
          items:
            type: string
        failureCodes:
          type: array
          items:
            type: string
          description: Codes of every check that is FAIL or INCONCLUSIVE.
        targetChallengeSha256:
          type:
            - string
            - 'null'
          pattern: ^[0-9a-f]{64}$
        expected:
          oneOf:
            - $ref: '#/components/schemas/ExpectedContract'
            - type: 'null'
        observedResponse:
          oneOf:
            - $ref: '#/components/schemas/ReportObservedResponse'
            - type: 'null'
        money:
          type: object
          required:
            - inboundTxId
            - downstreamSpendUsdc
            - unresolvedSpendUsdc
            - downstreamTxIds
            - payments
          properties:
            inboundTxId:
              type:
                - string
                - 'null'
            downstreamSpendUsdc:
              $ref: '#/components/schemas/DecimalAmount'
            unresolvedSpendUsdc:
              type: string
              pattern: ^[0-9]+\.[0-9]{2,6}$
              description: USDC held because a payment outcome is unknown.
            downstreamTxIds:
              type: array
              items:
                type: string
            payments:
              type: array
              items:
                $ref: '#/components/schemas/ReportPayment'
        scenarios:
          type: array
          items:
            $ref: '#/components/schemas/ReportScenario'
    ApiError:
      type: object
      description: Error body returned by every failing request.
      required:
        - error
        - message
      properties:
        error:
          type: string
          description: Stable machine-readable error code, for example `VALIDATION_FAILED`.
        message:
          type: string
          description: Human-readable explanation. Do not parse it.
    HttpMethod:
      type: string
      enum:
        - GET
        - POST
      description: HTTP method Selo uses to call the target.
    Verdict:
      type: string
      enum:
        - PASS
        - FAIL
        - INCONCLUSIVE
      description: Release verdict computed by the deterministic verdict reducer.
    InconclusiveReason:
      type: string
      enum:
        - NETWORK_UNAVAILABLE
        - FACILITATOR_UNAVAILABLE
        - TARGET_TIMEOUT
        - BUDGET_EXHAUSTED
        - PAYMENT_UNRESOLVED
        - EVIDENCE_INCOMPLETE
        - AUTHORIZATION_LAPSED
        - INTERNAL_ERROR
      description: Why a job ended INCONCLUSIVE. `null` on PASS and FAIL.
    CheckResult:
      type: object
      required:
        - id
        - status
        - code
        - blocking
        - summary
        - evidence
      properties:
        id:
          $ref: '#/components/schemas/CheckId'
        status:
          $ref: '#/components/schemas/CheckStatus'
        code:
          type: string
          description: >-
            Result code, for example `HANDSHAKE_VALID`, `SCHEMA_MISMATCH` or
            `NOT_RUN`. For `retry_safety` it is a `RetryOutcome`.
        blocking:
          type: boolean
          description: >-
            Whether the check can decide the verdict. Every check in the `quick`
            profile is blocking.
        summary:
          type: string
          description: One sentence describing what Selo observed.
        evidence:
          type: array
          items:
            type: string
            pattern: ^evd_[0-9A-HJKMNP-TV-Z]{26}$
          description: >-
            IDs of the evidence records behind this result. A PASS without
            evidence counts as INCONCLUSIVE.
    ExpectedContract:
      type: object
      additionalProperties: false
      description: >-
        What the paid response must look like. Omitted fields are not checked,
        except `status`, which defaults to 200.
      properties:
        status:
          type: integer
          minimum: 100
          maximum: 599
          default: 200
          description: Expected HTTP status of the paid response.
        contentType:
          type: string
          maxLength: 200
          pattern: ^[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]*/[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]*$
          description: Expected media type, `type/subtype`, compared case-insensitively.
        jsonSchema:
          type: object
          additionalProperties: true
          description: >-
            JSON Schema the paid response body must satisfy. Compiled with Ajv 8
            in strict mode; at most 16 KiB (16384 bytes) serialized. A schema
            that does not compile is rejected with 400.
    ReportObservedResponse:
      type: object
      required:
        - status
        - contentType
        - bodySha256
        - bodyBytes
        - txId
        - requestedAt
      properties:
        status:
          type: integer
        contentType:
          type:
            - string
            - 'null'
        bodySha256:
          type:
            - string
            - 'null'
          description: SHA-256 hex of the paid response body.
        bodyBytes:
          type:
            - integer
            - 'null'
          minimum: 0
        txId:
          type:
            - string
            - 'null'
          description: Settlement transaction the target reported and Selo accepted.
        requestedAt:
          type:
            - string
            - 'null'
          format: date-time
    DecimalAmount:
      type: string
      pattern: ^[0-9]+\.[0-9]{2,6}$
      description: >-
        USDC amount as a decimal string with 2 to 6 decimals, for example `1.00`
        or `0.01`.
    ReportPayment:
      type: object
      required:
        - status
        - amountUsdc
        - txId
        - expectedTxId
      properties:
        status:
          $ref: '#/components/schemas/PaymentStatus'
        amountUsdc:
          $ref: '#/components/schemas/DecimalAmount'
        txId:
          type:
            - string
            - 'null'
          description: Settled transaction ID.
        expectedTxId:
          type:
            - string
            - 'null'
          description: >-
            ID of the transaction Selo signed, recorded before sending, used to
            reconcile an unresolved payment.
    ReportScenario:
      type: object
      required:
        - check
        - operationId
        - status
        - attempts
        - durationMs
        - failureCode
      properties:
        check:
          $ref: '#/components/schemas/CheckId'
        operationId:
          type: string
          description: >-
            Immutable operation ID, `<jobId>:<check id>`. The replay reuses the
            paid request's operation ID as its `Idempotency-Key`.
        status:
          $ref: '#/components/schemas/ScenarioStatus'
        attempts:
          type: integer
          minimum: 0
        durationMs:
          type:
            - integer
            - 'null'
          minimum: 0
        failureCode:
          type:
            - string
            - 'null'
          description: The check's code when it did not PASS, otherwise `null`.
    CheckId:
      type: string
      enum:
        - handshake
        - paid_delivery
        - response_contract
        - discovery_contract
        - retry_safety
      description: The five release checks, always reported in this order.
    CheckStatus:
      type: string
      enum:
        - PASS
        - WARN
        - FAIL
        - INCONCLUSIVE
      description: Outcome of one check.
    PaymentStatus:
      type: string
      enum:
        - RESERVED
        - SETTLED
        - RELEASED
        - UNRESOLVED
      description: >-
        State of one downstream payment. `RESERVED`: budget held before signing.
        `SETTLED`: confirmed on chain. `RELEASED`: definitely not paid, budget
        returned. `UNRESOLVED`: outcome unknown, amount held and never released
        by a timeout.
    ScenarioStatus:
      type: string
      enum:
        - PLANNED
        - POLICY_CHECKED
        - RESERVED
        - REQUESTING
        - SETTLED
        - REJECTED
        - TIMEOUT_UNRESOLVED
        - EVALUATED
      description: State of one check's scenario inside a job.
  responses:
    InternalError:
      description: Unexpected server error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          examples:
            INTERNAL:
              summary: Unexpected server error
              value:
                error: INTERNAL
                message: Internal server error

````

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