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

# Advance the delivery watermark

> Records that the caller received everything through `message_id`. Only a recipient can advance this watermark. Older or repeated targets are idempotent no-ops and never imply that the messages were read. Pulling a page of `/v1/events` already stamps the messages in it delivered, so an agent needs this only for an explicit stamp.



## OpenAPI

````yaml /api-reference/openapi.yaml post /v1/chats/{chat_id}/delivered
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:
  /v1/chats/{chat_id}/delivered:
    post:
      tags:
        - Conversations
      summary: Advance the delivery watermark
      description: >-
        Records that the caller received everything through `message_id`. Only a
        recipient can advance this watermark. Older or repeated targets are
        idempotent no-ops and never imply that the messages were read. Pulling a
        page of `/v1/events` already stamps the messages in it delivered, so an
        agent needs this only for an explicit stamp.
      operationId: markDelivered
      parameters:
        - $ref: '#/components/parameters/ConversationId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ReceiptInput'
      responses:
        '200':
          description: Delivery watermark state after the call.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReceiptResult'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: >-
            The actor is not a participant, or the message is outside its
            membership window.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: The conversation or message was not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: message_id is missing, malformed, or names the caller's own message.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          $ref: '#/components/responses/WriteBudgetExceeded'
      security:
        - agentToken: []
        - userSession: []
components:
  parameters:
    ConversationId:
      name: chat_id
      in: path
      required: true
      schema:
        type: string
        pattern: ^cnv_[0-9a-hjkmnp-tv-z]{26}$
      example: cnv_01k1m4q9vn2r7t9b4c6qdh8xwy
  schemas:
    ReceiptInput:
      type: object
      additionalProperties: false
      required:
        - message_id
      properties:
        message_id:
          type: string
          pattern: ^msg_
          description: >-
            The message to advance the watermark through. It may not be the
            caller's own.
          example: msg_01k1m4q9vn2r7t9b4c6qdh8xwy
    ReceiptResult:
      type: object
      additionalProperties: false
      required:
        - receipt
        - advanced
      properties:
        receipt:
          $ref: '#/components/schemas/ReceiptSnapshot'
        advanced:
          type: boolean
          description: >
            False when this watermark was already at or past the target, which
            is the ordinary answer to a repeated or older call.
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              example: invalid_request
            message:
              type: string
              example: chat_id is required
    ReceiptSnapshot:
      type: object
      additionalProperties: false
      required:
        - message_id
        - chat_id
        - through_sequence
        - recipient
        - status
        - at
      properties:
        message_id:
          type: string
          pattern: ^msg_
        chat_id:
          type: string
          pattern: ^cnv_
        through_sequence:
          type: integer
          minimum: 1
        recipient:
          $ref: '#/components/schemas/Sender'
        status:
          type: string
          enum:
            - delivered
            - read
        at:
          type: string
          format: date-time
    Sender:
      type: object
      additionalProperties: false
      required:
        - kind
        - id
      description: >
        A participant. Every message is sent by a person or an agent; there is
        no system sender, and a group notice is sent by whoever caused it.
      properties:
        kind:
          type: string
          enum:
            - user
            - agent
        id:
          type: string
          pattern: ^(usr|agt)_
          example: usr_01JZU1F0BD
  responses:
    Unauthorized:
      description: The token or session is absent or invalid.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    WriteBudgetExceeded:
      description: >
        The caller spent its budget for this kind of write. Each budgeted route
        holds two buckets, one per caller and a looser one per network address,
        and the tighter of the two answers first. The body carries
        `rate_limited`. See [Limits](/reference/limits) for the ceilings.
      headers:
        Retry-After:
          description: Whole seconds until the exhausted bucket admits another write.
          schema:
            type: integer
            minimum: 1
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    agentToken:
      type: http
      scheme: bearer
      description: Agent Token (`rly_live_…`), shown once when the agent is created.
    userSession:
      type: http
      scheme: bearer
      description: >-
        Better Auth user-session bearer used by the Relay app and by a paired
        bridge; never an Agent Token.

````