> ## 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.

# Create an authorization

> Start proving that you control a target. Selo returns a one-time token; serve it as a line in `<origin>/.well-known/selo-verification.txt`, then call the verify endpoint. The authorization covers exactly one origin, path and method. The challenge stays open for one hour. This call is free and contacts nothing: Selo only parses the URL here.



## OpenAPI

````yaml /openapi.json post /v1/authorizations
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/authorizations:
    post:
      tags:
        - Authorizations
      summary: Create an authorization
      description: >-
        Start proving that you control a target. Selo returns a one-time token;
        serve it as a line in `<origin>/.well-known/selo-verification.txt`, then
        call the verify endpoint. The authorization covers exactly one origin,
        path and method. The challenge stays open for one hour. This call is
        free and contacts nothing: Selo only parses the URL here.
      operationId: createAuthorization
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateAuthorizationRequest'
            example:
              targetUrl: https://api.example.com/v1/orders
              method: POST
              project: orders-api
              contact: dev@example.com
      responses:
        '201':
          description: Authorization created in `PENDING` state.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthorizationChallenge'
              examples:
                created:
                  summary: Challenge to publish
                  value:
                    authorizationId: auth_…
                    status: PENDING
                    origin: https://api.example.com
                    routePath: /v1/orders
                    method: POST
                    verificationUrl: https://api.example.com/.well-known/selo-verification.txt
                    expectedContent: selo-verification=<token>
        '400':
          description: >-
            The body is not valid JSON, fails validation, or the target URL is
            refused.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              examples:
                VALIDATION_FAILED:
                  summary: Missing field
                  value:
                    error: VALIDATION_FAILED
                    message: |-
                      ✖ Invalid input: expected string, received undefined
                        → at contact
                INVALID_JSON:
                  summary: Body is not JSON
                  value:
                    error: VALIDATION_FAILED
                    message: Request body must be valid JSON
                TARGET_URL_INVALID:
                  summary: Not an absolute URL
                  value:
                    error: TARGET_URL_INVALID
                    message: The target URL is not a valid absolute URL
                TARGET_NOT_HTTPS:
                  summary: Not https
                  value:
                    error: TARGET_NOT_HTTPS
                    message: Only https targets can be authorized
                TARGET_ADDRESS_BLOCKED:
                  summary: IP literal, private name or custom port
                  value:
                    error: TARGET_ADDRESS_BLOCKED
                    message: >-
                      The target must be a public hostname on the default https
                      port
        '413':
          $ref: '#/components/responses/PayloadTooLarge'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  schemas:
    CreateAuthorizationRequest:
      type: object
      additionalProperties: false
      required:
        - targetUrl
        - method
        - project
        - contact
      properties:
        targetUrl:
          type: string
          maxLength: 2048
          format: uri
          description: >-
            Absolute `https` URL of the paid route. The hostname must be a
            public name (no IP literal, no single-label name such as
            `localhost`, no name ending in `.localhost`, `.local`, `.internal`,
            `.home.arpa` or `.lan`), on the default port, with no user name or
            password. The authorization covers this exact origin and path.
        method:
          $ref: '#/components/schemas/HttpMethod'
        project:
          type: string
          minLength: 1
          maxLength: 80
          description: >-
            Project name, 1 to 80 characters after trimming. It appears in the
            private report.
        contact:
          type: string
          minLength: 3
          maxLength: 200
          description: >-
            Contact for the target owner, 3 to 200 characters after trimming.
            Stored, not returned.
    AuthorizationChallenge:
      type: object
      description: >-
        A new authorization and the verification token to publish. The challenge
        stays open for one hour.
      required:
        - authorizationId
        - status
        - origin
        - routePath
        - method
        - verificationUrl
        - expectedContent
      properties:
        authorizationId:
          type: string
          description: Authorization ID, `auth_` plus 26 Crockford base32 characters.
        status:
          $ref: '#/components/schemas/AuthorizationStatus'
        origin:
          type: string
          description: Origin of the target URL, for example `https://api.example.com`.
        routePath:
          type: string
          description: Path of the target URL, without query string.
        method:
          $ref: '#/components/schemas/HttpMethod'
        verificationUrl:
          type: string
          description: >-
            Where Selo looks for the token:
            `<origin>/.well-known/selo-verification.txt`.
        expectedContent:
          type: string
          description: >-
            The exact line to serve in the verification file:
            `selo-verification=` followed by a 43-character base64url token.
            Selo stores only the SHA-256 of the token.
    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.
    AuthorizationStatus:
      type: string
      enum:
        - PENDING
        - VERIFIED
        - EXPIRED
        - REVOKED
      description: >-
        `PENDING`: challenge issued, not yet verified. `VERIFIED`: Selo found
        the token and may test the target until `expiresAt`. `EXPIRED`: the
        challenge or the authorization lapsed. `REVOKED`: the authorization was
        withdrawn.
  responses:
    PayloadTooLarge:
      description: The request body is larger than 64 KiB (65536 bytes).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          examples:
            PAYLOAD_TOO_LARGE:
              summary: Body over 64 KiB
              value:
                error: PAYLOAD_TOO_LARGE
                message: Request body exceeds 65536 bytes
    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.