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

# Propose a group

> Ask verified users who have installed the authenticated agent to join a new group or an existing group that already contains the agent. Relay commits one consent card into each target's direct conversation with the agent. The agent never changes membership directly. The first accept makes the conversation live, each later accept joins that same conversation, and the invite stays open for whoever has not answered until everyone answers or it expires.




## OpenAPI

````yaml /api-reference/openapi.yaml post /v1/groups/invites
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 public. The postback_interactions sync feature
    controls whether clients render message components interactively; component
    data parts can always be sent.
  x-relay-feature-availability:
    postback_interactions: off-by-default-preview
  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 finalized messages, pipe native agent output, and react.
  - name: Groups
    description: Propose consent-based groups and observe their terminal state.
  - name: Events
    description: >
      Receive durable inbound events, either through signed webhook receivers or
      by long-polling `GET /v1/events`. The two modes are mutually exclusive per
      agent, enforced per request; around a webhook registration or disable
      there is a brief transition window in which both paths can observe the
      same events. Delivery is at least once everywhere — always deduplicate by
      `event_id`.
  - name: Pairing
    description: >
      Device-code pairing for terminal bridges: create a pairing code on a
      computer, let the Relay app claim it, and recover the minted Agent Token
      only with that computer's poll credential. The token never travels to the
      phone.
  - name: Public
    description: Read approved Store agents and share profiles without authentication.
paths:
  /v1/groups/invites:
    post:
      tags:
        - Groups
      summary: Propose a group
      description: >
        Ask verified users who have installed the authenticated agent to join a
        new group or an existing group that already contains the agent. Relay
        commits one consent card into each target's direct conversation with the
        agent. The agent never changes membership directly. The first accept
        makes the conversation live, each later accept joins that same
        conversation, and the invite stays open for whoever has not answered
        until everyone answers or it expires.
      operationId: createGroupInvite
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GroupInviteCreateInput'
      responses:
        '201':
          description: Invite created, or the original response for an idempotent replay.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GroupInviteResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: >
            A target has not installed the agent, has blocked it, or the agent
            is not an active participant in the destination group.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: >
            The idempotency key conflicts, or an unexpired open invite already
            exists for the same agent, targets, and destination.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: >-
            The request shape, target set, TTL, existing membership, or group
            cap is invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: true
      schema:
        type: string
        minLength: 8
        maxLength: 255
      description: Deriving it from the triggering `event_id` makes a retry safe.
  schemas:
    GroupInviteCreateInput:
      type: object
      additionalProperties: false
      required:
        - title
        - user_ids
      properties:
        title:
          type: string
          minLength: 1
          maxLength: 100
          pattern: .*\S.*
        user_ids:
          type: array
          minItems: 1
          maxItems: 24
          uniqueItems: true
          items:
            type: string
            pattern: ^usr_
        reason:
          type: string
          minLength: 1
          maxLength: 200
          pattern: .*\S.*
        conversation_id:
          type: string
          pattern: ^cnv_
          description: >-
            Existing group in which the authenticated agent is active. Omit to
            propose a new group.
        ttl_seconds:
          type: integer
          default: 259200
          description: >-
            Requested lifetime in seconds. Relay clamps it to 600 through
            604800.
    GroupInviteResponse:
      type: object
      additionalProperties: false
      required:
        - invite
      properties:
        invite:
          $ref: '#/components/schemas/GroupInvite'
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              example: invalid_request
            message:
              type: string
              example: conversation_id is required
    GroupInvite:
      type: object
      additionalProperties: false
      required:
        - id
        - state
        - title
        - expires_at
        - created_at
        - members
      properties:
        id:
          type: string
          pattern: ^inv_
        state:
          type: string
          enum:
            - pending
            - active
            - completed
            - expired
          description: >
            pending is open with nobody joined yet, active is open with the
            conversation already live, completed is closed with a live
            conversation, and expired is closed without one.
        title:
          type: string
          minLength: 1
          maxLength: 100
        reason:
          type: string
          minLength: 1
          maxLength: 200
        conversation_id:
          type: string
          pattern: ^cnv_
          description: >
            The live conversation once the state is active or completed. On an
            invite into an existing group it also carries the destination while
            the state is pending, so read the caller's own member state before
            offering to open it.
        expires_at:
          type: string
          format: date-time
        created_at:
          type: string
          format: date-time
        members:
          type: array
          minItems: 1
          maxItems: 24
          items:
            $ref: '#/components/schemas/GroupInviteMember'
    GroupInviteMember:
      type: object
      additionalProperties: false
      required:
        - user_id
        - display_name
        - avatar_url
        - state
      properties:
        user_id:
          type: string
          pattern: ^usr_
        display_name:
          type: string
        avatar_url:
          type:
            - string
            - 'null'
        state:
          type: string
          enum:
            - invited
            - accepted
            - declined
          description: >
            invited has not answered yet, accepted is in the live conversation,
            and declined answered no.
  responses:
    Unauthorized:
      description: Token is absent or invalid.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    agentToken:
      type: http
      scheme: bearer
      description: Agent Token (`rly_live_…`), shown once at agent creation.

````