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

> ## Agent Instructions
> The Relay API base URL is https://api.relayapp.im. Never use workers.dev origins.
> The contract is raw HTTPS and JSON at https://api.relayapp.im. The one optional published package is @relaymessenger/cli. Import nothing else.
> One send is one message. Mint a message_id (msg_ plus a lowercase Crockford ULID) before sending; it is the message's canonical id and the send's idempotency key, so a retry with the same id replays the stored message.
> Message content is immutable. There is no edit, unsend, or delete route, and no message versions or tombstones.
> A reply is a pointer: reply_to is { message_id, part_id? } and the client draws the quote from the target.
> Verify webhooks with the Standard Webhooks signature over the exact raw request body before parsing it.
> Webhooks and GET /v1/events read the same durable log and can run at once. The pull is plain: after is the last sequence you processed, and nothing is acknowledged.
> An agent in a group is an ordinary member. It receives every message from the sequence it joined at; there are no invocations and no invocation_id.

# Request a device code

> Step one of RFC 8628 device authorization, and the way a terminal bridge pairs with a Relay account. No authentication; show the returned `user_code` (and a QR of `verification_uri_complete`) to the person, then poll `POST /api/auth/device/token` every `interval` seconds. Codes expire after `expires_in` seconds.

The person must open the verification URI before approving. That read is what binds the pending request to their account; approving a code nobody has opened answers `400 invalid_request`.




## OpenAPI

````yaml /api-reference/openapi.yaml post /api/auth/device/code
openapi: 3.1.0
info:
  title: Relay developer API
  version: '0.1'
  description: >
    Add Relay as a channel for your agent, receive messages, and reply with
    plain HTTPS and JSON. Authenticate every request with an Agent Token unless
    the endpoint is marked otherwise. Data parts are stored and delivered as
    sent and render through their fallback text, except for the reserved
    `data.type` values Relay resolves itself.
  license:
    name: Proprietary
    identifier: LicenseRef-Proprietary
servers:
  - url: https://api.relayapp.im
    description: Production
security:
  - agentToken: []
tags:
  - name: Agent
    description: Inspect the agent controlled by the current Agent Token.
  - name: Messages
    description: Send a message, read history, and react.
  - name: Conversations
    description: >
      List the conversations an agent is in, advance receipts, and show the
      typing indicator.
  - name: Events
    description: >
      Receive durable inbound events, either through signed webhook receivers or
      by pulling `GET /v1/events`. Both work at once: one durable log per agent
      feeds both transports. Delivery is at least once everywhere; always
      deduplicate by `event_id`.
  - name: Attachments
    description: Upload bytes once and reference them from any number of parts.
  - name: Pairing
    description: >
      Device authorization (RFC 8628) for terminal bridges. Four calls, in this
      order: the computer asks for a code, the person opens the verification URI
      so the code is claimed for their account, the person approves it, and the
      computer exchanges the code for a session it uses to provision its agent
      and mint that agent's token. The token never travels to the phone.
  - name: Public
    description: Share profiles.
paths:
  /api/auth/device/code:
    post:
      tags:
        - Pairing
      summary: Request a device code
      description: >
        Step one of RFC 8628 device authorization, and the way a terminal bridge
        pairs with a Relay account. No authentication; show the returned
        `user_code` (and a QR of `verification_uri_complete`) to the person,
        then poll `POST /api/auth/device/token` every `interval` seconds. Codes
        expire after `expires_in` seconds.


        The person must open the verification URI before approving. That read is
        what binds the pending request to their account; approving a code nobody
        has opened answers `400 invalid_request`.
      operationId: requestDeviceCode
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - client_id
              properties:
                client_id:
                  type: string
                  description: The identifier of the bridge asking to pair.
                  example: relay-cli
                scope:
                  type: string
                  description: Space-separated scopes, when the bridge asks for any.
      responses:
        '200':
          description: Codes issued; show the user code and start polling.
          content:
            application/json:
              schema:
                type: object
                required:
                  - device_code
                  - user_code
                  - verification_uri
                  - verification_uri_complete
                  - expires_in
                  - interval
                properties:
                  device_code:
                    type: string
                    description: The bridge's secret half. Never show it to the person.
                  user_code:
                    type: string
                    description: The short code the person types into the Relay app.
                    example: ABCD-EFGH
                  verification_uri:
                    type: string
                    format: uri
                  verification_uri_complete:
                    type: string
                    format: uri
                    description: >-
                      The same URI with the user code embedded, for a QR or a
                      deep link.
                  expires_in:
                    type: integer
                    description: Seconds until the codes stop being claimable.
                    example: 600
                  interval:
                    type: integer
                    description: Minimum seconds between token polls.
                    example: 5
        '400':
          description: |
            `invalid_request` or `invalid_client`, in the RFC 8628 error shape.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeviceAuthorizationError'
      security: []
components:
  schemas:
    DeviceAuthorizationError:
      type: object
      description: >
        The RFC 8628 error shape, which is not Relay's `Error` envelope: the
        device endpoints answer in the OAuth idiom their clients already parse.
      required:
        - error
        - error_description
      properties:
        error:
          type: string
          example: authorization_pending
        error_description:
          type: string
  securitySchemes:
    agentToken:
      type: http
      scheme: bearer
      description: Agent Token (`rly_live_…`), shown once when the agent is created.

````