---
openapi: 3.0.1
info:
  title: Session Replay API
  version: v1
  description: Session Replay provides an API for capturing bug reports with full
    context - replays, the sites and teams they belong to, team membership, webhook
    destinations and authentication - in JSON:API format.
paths:
  "/api/v1/auth/login":
    post:
      summary: Obtain an access token
      tags:
      - Auth
      description: 'Exchange credentials for a token pair, or exchange a refresh token
        for a fresh one. grant_type decides which: ''password'' (the default) reads
        email and password, ''refresh_token'' reads refresh_token.'
      parameters: []
      responses:
        '200':
          description: tokens issued
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                      type:
                        type: string
                        enum:
                        - auth_token
                      attributes:
                        type: object
                        properties:
                          access_token:
                            type: string
                          refresh_token:
                            type: string
                          token_type:
                            type: string
                            enum:
                            - Bearer
                          scope:
                            type: string
                            description: The scopes granted, space delimited
                          expires_in:
                            type: integer
                            description: Access token life in seconds
                          refresh_expires_in:
                            type: integer
                            description: Refresh token life in seconds
                  included:
                    type: array
                    items:
                      type: object
                    description: The user and the api_session the tokens belong to
        '400':
          description: unsupported grant_type
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: invalid credentials
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                grant_type:
                  type: string
                  enum:
                  - password
                  - refresh_token
                  description: Defaults to password
                email:
                  type: string
                  description: Password grant only
                password:
                  type: string
                  description: Password grant only
                name:
                  type: string
                  description: Label for the session being created
                refresh_token:
                  type: string
                  description: Refresh token grant only
  "/api/v1/auth/exchange":
    post:
      summary: Trade a browser authorization for tokens
      tags:
      - Auth
      description: Second half of the browser authorization flow. A tool opens /authorize
        in a browser, is redirected back to its own loopback address with a code,
        and trades that code here for a token pair. Codes are single use and expire
        within minutes, must be redeemed against the same redirect_uri they were issued
        for, and must be presented with the code_verifier whose SHA-256 was sent as
        the code_challenge on the authorization request.
      parameters: []
      responses:
        '200':
          description: tokens issued
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                      type:
                        type: string
                        enum:
                        - auth_token
                      attributes:
                        type: object
                        properties:
                          access_token:
                            type: string
                          refresh_token:
                            type: string
                          token_type:
                            type: string
                            enum:
                            - Bearer
                          scope:
                            type: string
                            description: The scopes granted, space delimited
                          expires_in:
                            type: integer
                            description: Access token life in seconds
                          refresh_expires_in:
                            type: integer
                            description: Refresh token life in seconds
                  included:
                    type: array
                    items:
                      type: object
                    description: The user and the api_session the tokens belong to
        '400':
          description: code, redirect_uri or code_verifier missing
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: code unknown, expired, already used, issued for another destination,
            or presented with the wrong verifier
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
              - code
              - redirect_uri
              - code_verifier
              properties:
                code:
                  type: string
                  description: The code the redirect carried back
                redirect_uri:
                  type: string
                  description: The loopback address the code was issued for
                code_verifier:
                  type: string
                  description: The secret behind the code_challenge sent to /authorize
  "/api/v1/auth/logout":
    delete:
      summary: Revoke the current session
      tags:
      - Auth
      description: Revokes the session the access token belongs to, so both of its
        tokens stop working.
      security:
      - bearer_auth: []
      parameters:
      - name: Authorization
        in: header
        description: Bearer token
        schema:
          type: string
      responses:
        '200':
          description: session revoked
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    nullable: true
                  meta:
                    type: object
                    properties:
                      message:
                        type: string
        '401':
          description: missing or invalid token
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/api/v1/me":
    get:
      summary: Current browser session user
      tags:
      - Current user
      description: Who the browser session belongs to. Authenticated by the site's
        own session cookie rather than a token, because this is what the extension
        calls once the user has signed in on the site. Passing extension_id hands
        any replay captured anonymously from that installation to the signed-in user.
      parameters:
      - name: extension_id
        in: query
        required: false
        schema:
          type: string
        description: Installation id of the extension asking
      responses:
        '200':
          description: signed in
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                      type:
                        type: string
                        enum:
                        - user
                      attributes:
                        type: object
                        properties:
                          email:
                            type: string
                          first_name:
                            type: string
                            nullable: true
                          last_name:
                            type: string
                            nullable: true
                          full_name:
                            type: string
                            nullable: true
                          initials:
                            type: string
                            nullable: true
                          roles:
                            type: array
                            items:
                              type: string
                          referral_code:
                            type: string
                  meta:
                    type: object
                    properties:
                      claimed_replays:
                        type: integer
                        description: How many anonymous replays were handed over on
                          this call
        '401':
          description: no browser session
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/api/v1/session":
    delete:
      summary: Sign out of the browser session
      tags:
      - Current user
      description: Ends the site session the extension is riding on. Same cookie authentication
        as /api/v1/me.
      responses:
        '200':
          description: signed out
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      type:
                        type: string
                        enum:
                        - session
                      attributes:
                        type: object
                        properties:
                          signed_out:
                            type: boolean
        '401':
          description: no browser session
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/api/v1/memberships":
    get:
      summary: List memberships
      tags:
      - Memberships
      description: Every membership of every team the caller belongs to, newest first.
        A membership with no user and an invite_email is an invitation that has not
        been accepted yet.
      security:
      - bearer_auth: []
      parameters:
      - name: Authorization
        in: header
        description: Bearer token
        schema:
          type: string
      - name: page[after]
        in: query
        required: false
        description: Cursor for pagination (after this cursor)
        schema:
          type: string
      - name: page[size]
        in: query
        required: false
        description: Page size (max 100, default 25)
        schema:
          type: integer
      responses:
        '200':
          description: successful
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/Membership"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                  links:
                    "$ref": "#/components/schemas/PaginationLinks"
        '401':
          description: unauthorized
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/api/v1/memberships/{id}":
    parameters:
    - name: id
      in: path
      description: Membership id
      required: true
      schema:
        type: string
    get:
      summary: Show a membership
      tags:
      - Memberships
      security:
      - bearer_auth: []
      parameters:
      - name: Authorization
        in: header
        description: Bearer token
        schema:
          type: string
      - name: include
        in: query
        required: false
        description: Include related resources (e.g., 'user,team')
        schema:
          type: string
      responses:
        '200':
          description: successful
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    "$ref": "#/components/schemas/Membership"
                  included:
                    type: array
                    items:
                      type: object
        '403':
          description: not a member of that team
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
        '404':
          description: no such membership
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
    put:
      summary: Update a membership
      tags:
      - Memberships
      description: Team admins change roles; a member may update their own membership,
        which is how an invitation is accepted.
      security:
      - bearer_auth: []
      parameters:
      - name: Authorization
        in: header
        description: Bearer token
        schema:
          type: string
      responses:
        '200':
          description: membership updated
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    "$ref": "#/components/schemas/Membership"
                  meta:
                    type: object
                    properties:
                      message:
                        type: string
        '403':
          description: neither the member nor a team admin
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/vnd.api+json:
            schema:
              type: object
              properties:
                data:
                  type: object
                  properties:
                    type:
                      type: string
                      enum:
                      - membership
                    attributes:
                      type: object
                      properties:
                        role:
                          type: string
                          enum:
                          - owner
                          - admin
                          - member
    delete:
      summary: Remove a membership
      tags:
      - Memberships
      description: Team admins remove members; a member may remove their own membership
        to leave.
      security:
      - bearer_auth: []
      parameters:
      - name: Authorization
        in: header
        description: Bearer token
        schema:
          type: string
      responses:
        '200':
          description: membership removed
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    nullable: true
                  meta:
                    type: object
                    properties:
                      message:
                        type: string
        '403':
          description: neither the member nor a team admin
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/api/v1/replays/{id}/answers":
    post:
      summary: Answer the domain's questions about a report
      tags:
      - Replays
      description: 'What the reporter answered to the questions the domain''s owner
        asks, posted after the report they belong to rather than with it - the panel
        asks them once the share link is already on screen. Two ways to be allowed:
        anonymously, with the replay id in the path AND the extension id the report
        was filed with, both matching the stored report; or signed in, as the report''s
        own submitter. The share token is not a key here - it exists to be forwarded.
        A report filed through the integration library carries no extension id, so
        it can only be answered by a signed-in submitter. Posting again replaces the
        previous answers, so a retry is harmless. Every refusal of the poster is the
        same 404, whatever was wrong. The whole request may not exceed 64 KB; one
        that does, or one that declares no length, is refused with 413 and the error
        code ''answers_too_large''.'
      parameters:
      - name: id
        in: path
        description: The replay's id, as returned when it was created
        required: true
        schema:
          type: string
      responses:
        '200':
          description: answers stored, replacing anything posted before
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        type:
                          type: string
                          enum:
                          - replay_question_answers
                        attributes:
                          type: object
                          properties:
                            site_question_id:
                              type: string
                              nullable: true
                            question_text:
                              type: string
                            value:
                              type: array
                              items:
                                type: string
                            position:
                              type: integer
        '404':
          description: not this report's to answer - or no such report, which answers
            the same way
        '413':
          description: answers larger than the size ceiling
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
        '422':
          description: a body that is not a set of answers - no answers list at all,
            an entry that is not an answer, a value that is not text, or more answers
            than a domain is allowed to ask for
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                extension_id:
                  type: string
                  description: The installation that filed the report. Required unless
                    signed in as its submitter.
                answers:
                  type: array
                  maxItems: 2
                  description: 'In the order the questions were asked. A question
                    that was skipped is left out rather than sent empty - an entry
                    with no values stores no row. Required: leaving it out is refused
                    rather than read as an empty list, so a retry whose body was truncated
                    cannot erase what was already stored. An explicit empty list does
                    clear them, which is how an answer is taken back.'
                  items:
                    type: object
                    properties:
                      site_question_id:
                        type: string
                        nullable: true
                        description: The question answered. Null on the generic question,
                          and kept only when it still names a question this domain
                          asks - a question removed since leaves the answer readable
                          and drops the link.
                      question_text:
                        type: string
                        description: The question as it was put to the reporter. Stored
                          on the answer, so an owner rewriting a question does not
                          change what an older report appears to have been asked.
                      value:
                        description: The answer. A list for checkboxes, and either
                          a list or a bare string for the types that take one.
                        oneOf:
                        - type: array
                          items:
                            type: string
                        - type: string
                    required:
                    - question_text
                    - value
              required:
              - answers
        required: true
  "/api/v1/replays":
    post:
      summary: Create replay (screenshot or video)
      tags:
      - Replays
      description: 'Create a new replay. Supports three authentication methods: Site
        API Key (recommended), JWT token, or anonymous. Two types supported: ''screenshot''
        for quick snapshots with basic metadata, ''video'' for full session recordings
        with extended metadata. The whole request may not exceed 600 MB. One that
        does, or one that declares no length, is refused with 413 and the error code
        ''replay_too_large'' before anything is stored, and the accompanying detail
        is written to be shown to the person reporting the bug.'
      parameters:
      - name: X-Site-API-Key
        in: header
        required: false
        description: Site API key for authentication (get from Site Settings)
        schema:
          type: string
      - name: Authorization
        in: header
        required: false
        description: JWT Bearer token (alternative to API key)
        schema:
          type: string
      responses:
        '201':
          description: video replay created with extended metadata
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        format: uuid
                      type:
                        type: string
                        enum:
                        - replay
                      attributes:
                        type: object
                        properties:
                          url:
                            type: string
                          page_title:
                            type: string
                          replay_type:
                            type: string
                            enum:
                            - screenshot
                            - video
                          share_token:
                            type: string
                            description: Unique share token for public URL
                          share_url:
                            type: string
                            description: Public share URL
                          owner_key:
                            type: string
                            description: Key for this one report, returned to whoever
                              uploaded it and presented once as ?owner_key= when opening
                              it, so the reporter's own reading is not counted as
                              a view
                          zip_url:
                            type: string
                            description: URL to download the original ZIP file
                          user_agent:
                            type: string
                            nullable: true
                          browser_info:
                            type: object
                          screen_size:
                            type: object
                          capture_surface:
                            type: string
                            enum:
                            - browser
                            - monitor
                            - window
                            nullable: true
                          share_expires_at:
                            type: string
                            format: date-time
                          share_view_count:
                            type: integer
                          resolution_status:
                            type: string
                            enum:
                            - pending
                            - in_progress
                            - resolved
                            - wont_fix
                          resolved_at:
                            type: string
                            format: date-time
                            nullable: true
                          expired:
                            type: boolean
                          network_data:
                            type: array
                            items:
                              type: object
                          interactions_data:
                            type: array
                            items:
                              type: object
                          console_logs:
                            type: array
                            items:
                              type: object
                            description: Captured console lines, repeats collapsed
                              into one entry carrying count, first_timestamp and last_timestamp
                          created_at:
                            type: string
                            format: date-time
                          updated_at:
                            type: string
                            format: date-time
                        required:
                        - url
                        - share_token
                        - share_url
                        - replay_type
                      relationships:
                        type: object
                        properties:
                          site:
                            type: object
                            properties:
                              data:
                                type: object
                                nullable: true
                                properties:
                                  id:
                                    type: string
                                  type:
                                    type: string
                                    enum:
                                    - site
                          submitter:
                            type: object
                            properties:
                              data:
                                type: object
                                nullable: true
                                properties:
                                  id:
                                    type: string
                                  type:
                                    type: string
                                    enum:
                                    - user
                  meta:
                    type: object
                    properties:
                      message:
                        type: string
        '401':
          description: invalid API key
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
        '413':
          description: upload larger than the size ceiling
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
        '422':
          description: invalid request
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: file
          application/vnd.api+json:
            schema:
              type: file
        description: ZIP file containing metadata.json and recording file (RECOMMENDED
          - uploads directly to S3, can be reprocessed)
    get:
      summary: List replays
      tags:
      - Replays
      description: Get a paginated list of replays (requires authentication - returns
        user's own replays and team replays)
      security:
      - bearer_auth: []
      parameters:
      - name: Authorization
        in: header
        description: Bearer token
        schema:
          type: string
      - name: page[after]
        in: query
        required: false
        description: Cursor for pagination (after this cursor)
        schema:
          type: string
      - name: page[before]
        in: query
        required: false
        description: Cursor for reverse pagination (before this cursor)
        schema:
          type: string
      - name: page[size]
        in: query
        required: false
        description: Page size (max 100, default 25)
        schema:
          type: integer
      - name: filter[replay_type]
        in: query
        type: string
        required: false
        description: Filter by type
        schema:
          type: string
          enum:
          - screenshot
          - video
      - name: filter[resolution_status]
        in: query
        type: string
        required: false
        description: Filter by status
        schema:
          type: string
          enum:
          - pending
          - in_progress
          - resolved
          - wont_fix
      - name: include
        in: query
        required: false
        description: Include related resources (e.g., 'site,submitter')
        schema:
          type: string
      responses:
        '200':
          description: successful
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        type:
                          type: string
                          enum:
                          - replay
                        attributes:
                          type: object
                  meta:
                    type: object
                    properties:
                      page_size:
                        type: integer
                      has_next_page:
                        type: boolean
                      has_previous_page:
                        type: boolean
                      count:
                        type: integer
                  links:
                    type: object
                    properties:
                      self:
                        type: string
                      next:
                        type: string
                        nullable: true
                      prev:
                        type: string
                        nullable: true
        '401':
          description: unauthorized
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/api/v1/replays/{id}":
    parameters:
    - name: id
      in: path
      description: Replay ID
      required: true
      schema:
        type: string
    get:
      summary: Show replay
      tags:
      - Replays
      description: Get a specific replay (requires authentication)
      security:
      - bearer_auth: []
      parameters:
      - name: Authorization
        in: header
        description: Bearer token
        schema:
          type: string
      - name: include
        in: query
        required: false
        description: Include related resources (e.g., 'site,submitter')
        schema:
          type: string
      responses:
        '200':
          description: successful
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                      type:
                        type: string
                      attributes:
                        type: object
        '404':
          description: replay not found
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
    patch:
      summary: Update replay
      tags:
      - Replays
      description: 'Update a replay (requires team membership or ownership). An update
        may carry a recording, so it takes the same 600 MB ceiling the upload does
        and is refused the same way: 413 with the error code ''replay_too_large''.'
      security:
      - bearer_auth: []
      parameters:
      - name: Authorization
        in: header
        description: Bearer token
        schema:
          type: string
      responses:
        '200':
          description: replay updated
        '403':
          description: forbidden
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
        '413':
          description: update larger than the size ceiling
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/vnd.api+json:
            schema:
              type: object
              properties:
                data:
                  type: object
                  properties:
                    type:
                      type: string
                      enum:
                      - replay
                    id:
                      type: string
                    attributes:
                      type: object
                      properties:
                        page_title:
                          type: string
                        resolution_status:
                          type: string
                          enum:
                          - pending
                          - in_progress
                          - resolved
                          - wont_fix
                  required:
                  - type
                  - id
              required:
              - data
    delete:
      summary: Delete replay
      tags:
      - Replays
      description: Delete a replay (requires team membership or ownership)
      security:
      - bearer_auth: []
      parameters:
      - name: Authorization
        in: header
        description: Bearer token
        schema:
          type: string
      responses:
        '200':
          description: replay deleted
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    nullable: true
                  meta:
                    type: object
                    properties:
                      message:
                        type: string
        '403':
          description: forbidden
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/api/v1/replays/{id}/frame":
    parameters:
    - name: id
      in: path
      description: Replay ID
      required: true
      schema:
        type: string
    get:
      summary: Extract a frame from a replay's recording
      tags:
      - Replays
      description: Return a single still from the replay's screen recording at the
        offset given, extracted per request and never stored. The image is JPEG, scaled
        down to the requested width and never scaled up past the recording's own size.
        Screenshot reports have no recording and are refused.
      security:
      - bearer_auth: []
      parameters:
      - name: Authorization
        in: header
        description: Bearer token
        schema:
          type: string
      - name: offset_ms
        in: query
        required: true
        description: Moment in the recording, in milliseconds from its start - the
          same unit the replay's own duration and log offsets use
        schema:
          type: integer
      - name: width
        in: query
        required: false
        description: Widest the frame may be, in pixels (64-2560, default 1280). A
          narrower recording is returned at its own width.
        schema:
          type: integer
      responses:
        '200':
          description: frame extracted
          content:
            image/jpeg:
              schema:
                type: string
                format: binary
        '422':
          description: the report is a screenshot or lost its recording - a JSON:API
            error document
        '400':
          description: the offset or width is not a value the endpoint accepts - a
            JSON:API error document
        '401':
          description: unauthorized - a JSON:API error document
        '403':
          description: the replay belongs to somebody else - a JSON:API error document
  "/api/v1/sites":
    get:
      summary: List sites
      tags:
      - Sites
      description: The sites of every team the caller owns or belongs to, newest first.
      security:
      - bearer_auth: []
      parameters:
      - name: Authorization
        in: header
        description: Bearer token
        schema:
          type: string
      - name: page[after]
        in: query
        required: false
        description: Cursor for pagination (after this cursor)
        schema:
          type: string
      - name: page[size]
        in: query
        required: false
        description: Page size (max 100, default 25)
        schema:
          type: integer
      - name: q
        in: query
        required: false
        description: Free text search
        schema:
          type: string
      - name: team_id
        in: query
        required: false
        description: Only the sites of this team. A team you neither own nor belong
          to lists nothing.
        schema:
          type: string
      responses:
        '200':
          description: successful
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/Site"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                  links:
                    "$ref": "#/components/schemas/PaginationLinks"
        '401':
          description: unauthorized
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
    post:
      summary: Claim a site
      tags:
      - Sites
      description: Claims a domain for the caller's own team. Claiming a domain is
        a paid feature, so a team with no plan, or one already at its domain limit,
        is refused.
      security:
      - bearer_auth: []
      parameters:
      - name: Authorization
        in: header
        description: Bearer token
        schema:
          type: string
      responses:
        '201':
          description: site claimed
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    "$ref": "#/components/schemas/Site"
                  meta:
                    type: object
                    properties:
                      message:
                        type: string
        '422':
          description: invalid, or the plan does not allow another domain
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: unauthorized
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/vnd.api+json:
            schema:
              type: object
              properties:
                data:
                  type: object
                  properties:
                    type:
                      type: string
                      enum:
                      - site
                    attributes:
                      type: object
                      properties:
                        name:
                          type: string
                        domain:
                          type: string
                          description: Hostname only - no scheme, path or port
                      required:
                      - domain
                  required:
                  - type
                  - attributes
              required:
              - data
  "/api/v1/sites/{id}":
    parameters:
    - name: id
      in: path
      description: Site id
      required: true
      schema:
        type: string
    get:
      summary: Show a site
      tags:
      - Sites
      security:
      - bearer_auth: []
      parameters:
      - name: Authorization
        in: header
        description: Bearer token
        schema:
          type: string
      - name: include
        in: query
        required: false
        description: Include related resources (e.g., 'team')
        schema:
          type: string
      responses:
        '200':
          description: successful
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    "$ref": "#/components/schemas/Site"
                  included:
                    type: array
                    items:
                      type: object
        '403':
          description: not the caller's site
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
        '404':
          description: no such site
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
    put:
      summary: Update a site
      tags:
      - Sites
      description: Team admins only. Retention and tier are not settable here - both
        follow the team's plan.
      security:
      - bearer_auth: []
      parameters:
      - name: Authorization
        in: header
        description: Bearer token
        schema:
          type: string
      responses:
        '200':
          description: site updated
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    "$ref": "#/components/schemas/Site"
                  meta:
                    type: object
                    properties:
                      message:
                        type: string
        '403':
          description: not a team admin
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/vnd.api+json:
            schema:
              type: object
              properties:
                data:
                  type: object
                  properties:
                    type:
                      type: string
                      enum:
                      - site
                    attributes:
                      type: object
                      properties:
                        name:
                          type: string
                        domain:
                          type: string
    delete:
      summary: Delete a site
      tags:
      - Sites
      description: Team owner only. Deletes the site's replays with it.
      security:
      - bearer_auth: []
      parameters:
      - name: Authorization
        in: header
        description: Bearer token
        schema:
          type: string
      responses:
        '200':
          description: site deleted
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    nullable: true
                  meta:
                    type: object
                    properties:
                      message:
                        type: string
        '403':
          description: not the team owner
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/api/v1/teams":
    get:
      summary: List teams
      tags:
      - Teams
      description: The teams the caller owns or is a member of, newest first.
      security:
      - bearer_auth: []
      parameters:
      - name: Authorization
        in: header
        description: Bearer token
        schema:
          type: string
      - name: page[after]
        in: query
        required: false
        description: Cursor for pagination (after this cursor)
        schema:
          type: string
      - name: page[size]
        in: query
        required: false
        description: Page size (max 100, default 25)
        schema:
          type: integer
      responses:
        '200':
          description: successful
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/Team"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                  links:
                    "$ref": "#/components/schemas/PaginationLinks"
        '401':
          description: unauthorized
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
    post:
      summary: Create a team
      tags:
      - Teams
      description: The caller becomes the team's owner.
      security:
      - bearer_auth: []
      parameters:
      - name: Authorization
        in: header
        description: Bearer token
        schema:
          type: string
      responses:
        '201':
          description: team created
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    "$ref": "#/components/schemas/Team"
                  meta:
                    type: object
                    properties:
                      message:
                        type: string
        '422':
          description: invalid
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: unauthorized
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/vnd.api+json:
            schema:
              type: object
              properties:
                data:
                  type: object
                  properties:
                    type:
                      type: string
                      enum:
                      - team
                    attributes:
                      type: object
                      properties:
                        name:
                          type: string
                      required:
                      - name
                  required:
                  - type
                  - attributes
              required:
              - data
  "/api/v1/teams/{id}":
    parameters:
    - name: id
      in: path
      description: Team id
      required: true
      schema:
        type: string
    get:
      summary: Show a team
      tags:
      - Teams
      security:
      - bearer_auth: []
      parameters:
      - name: Authorization
        in: header
        description: Bearer token
        schema:
          type: string
      - name: include
        in: query
        required: false
        description: Include related resources (e.g., 'owner,sites')
        schema:
          type: string
      responses:
        '200':
          description: successful
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    "$ref": "#/components/schemas/Team"
                  included:
                    type: array
                    items:
                      type: object
        '403':
          description: not a member
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
        '404':
          description: no such team
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
    put:
      summary: Update a team
      tags:
      - Teams
      description: Team admins only.
      security:
      - bearer_auth: []
      parameters:
      - name: Authorization
        in: header
        description: Bearer token
        schema:
          type: string
      responses:
        '200':
          description: team updated
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    "$ref": "#/components/schemas/Team"
                  meta:
                    type: object
                    properties:
                      message:
                        type: string
        '403':
          description: not a team admin
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/vnd.api+json:
            schema:
              type: object
              properties:
                data:
                  type: object
                  properties:
                    type:
                      type: string
                      enum:
                      - team
                    attributes:
                      type: object
                      properties:
                        name:
                          type: string
    delete:
      summary: Delete a team
      tags:
      - Teams
      description: Team owner only.
      security:
      - bearer_auth: []
      parameters:
      - name: Authorization
        in: header
        description: Bearer token
        schema:
          type: string
      responses:
        '200':
          description: team deleted
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    nullable: true
                  meta:
                    type: object
                    properties:
                      message:
                        type: string
        '403':
          description: not the team owner
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/api/v1/webhook_destinations":
    post:
      summary: Subscribe a webhook to events
      tags:
      - Webhook destinations
      description: 'Registers a URL of yours against a team you administer. Name the
        team with team_id, or leave it out and the destination is attached to your
        personal team. The response carries the signing key once, on create: every
        delivery is signed with it and there is no second chance to read it over the
        API.'
      security:
      - bearer_auth: []
      parameters:
      - name: Authorization
        in: header
        description: Bearer token
        schema:
          type: string
      responses:
        '201':
          description: destination created
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    "$ref": "#/components/schemas/WebhookDestination"
                  meta:
                    type: object
                    properties:
                      message:
                        type: string
        '404':
          description: no such team for this caller
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
        '422':
          description: the url cannot be reached
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: unauthorized
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/vnd.api+json:
            schema:
              type: object
              properties:
                data:
                  type: object
                  properties:
                    type:
                      type: string
                      enum:
                      - webhook_destination
                    attributes:
                      type: object
                      properties:
                        url:
                          type: string
                          description: HTTPS address a delivery is posted to
                        events:
                          type: array
                          items:
                            type: string
                        team_id:
                          type: string
                          format: uuid
                          description: Team the destination belongs to, defaulting
                            to your personal team
                        site_id:
                          type: string
                          format: uuid
                          description: Deliver only for this site of the team
                        all_sites:
                          type: boolean
                          description: Deliver for every site of the team. Defaults
                            to true when no site is named
                        site_ids:
                          type: array
                          items:
                            type: string
                            format: uuid
                          description: Deliver only for these sites of the team, with
                            all_sites false
                      required:
                      - url
                      - events
                  required:
                  - type
                  - attributes
              required:
              - data
  "/api/v1/webhook_destinations/{id}":
    parameters:
    - name: id
      in: path
      description: Webhook destination id
      required: true
      schema:
        type: string
    delete:
      summary: Unsubscribe a webhook
      tags:
      - Webhook destinations
      description: Removes a destination of a team you administer. A destination belonging
        to any other team answers as though it does not exist.
      security:
      - bearer_auth: []
      parameters:
      - name: Authorization
        in: header
        description: Bearer token
        schema:
          type: string
      responses:
        '200':
          description: destination removed
          content:
            application/vnd.api+json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    nullable: true
                  meta:
                    type: object
                    properties:
                      message:
                        type: string
        '404':
          description: no such destination for this team
          content:
            application/vnd.api+json:
              schema:
                "$ref": "#/components/schemas/Error"
servers:
- url: https://session-replay.com
  description: Production
- url: https://staging.session-replay.com
  description: Staging
- url: http://localhost:4006
  description: Local development
components:
  securitySchemes:
    bearer_auth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: JWT authentication token
  schemas:
    Error:
      type: object
      properties:
        errors:
          type: array
          items:
            type: object
            properties:
              status:
                type: string
              code:
                type: string
              title:
                type: string
              detail:
                type: string
    Membership:
      type: object
      properties:
        id:
          type: string
          format: uuid
        type:
          type: string
          enum:
          - membership
        attributes:
          type: object
          properties:
            role:
              type: string
              enum:
              - owner
              - admin
              - member
            invite_email:
              type: string
              nullable: true
            accepted_at:
              type: string
              format: date-time
              nullable: true
            created_at:
              type: string
              format: date-time
            updated_at:
              type: string
              format: date-time
        relationships:
          type: object
    PaginationMeta:
      type: object
      properties:
        page_size:
          type: integer
        has_next_page:
          type: boolean
        has_previous_page:
          type: boolean
        count:
          type: integer
    PaginationLinks:
      type: object
      properties:
        self:
          type: string
        next:
          type: string
          nullable: true
        prev:
          type: string
          nullable: true
    Site:
      type: object
      properties:
        id:
          type: string
          format: uuid
        type:
          type: string
          enum:
          - site
        attributes:
          type: object
          properties:
            name:
              type: string
            domain:
              type: string
            tier:
              type: string
              enum:
              - free
              - starter
              - pro
              - enterprise
            replay_retention_days:
              type: integer
              nullable: true
            replays_count:
              type: integer
            created_at:
              type: string
              format: date-time
            updated_at:
              type: string
              format: date-time
        relationships:
          type: object
    Team:
      type: object
      properties:
        id:
          type: string
          format: uuid
        type:
          type: string
          enum:
          - team
        attributes:
          type: object
          properties:
            name:
              type: string
            created_at:
              type: string
              format: date-time
            updated_at:
              type: string
              format: date-time
        relationships:
          type: object
    WebhookDestination:
      type: object
      properties:
        id:
          type: string
          format: uuid
        type:
          type: string
          enum:
          - webhook_destination
        attributes:
          type: object
          properties:
            team_id:
              type: string
              format: uuid
            url:
              type: string
            events:
              type: array
              items:
                type: string
            auto_send:
              type: boolean
            all_sites:
              type: boolean
            secret:
              type: string
              description: Signing key, returned once, on create - the only way to
                verify a delivery
            created_at:
              type: string
              format: date-time
            updated_at:
              type: string
              format: date-time
        relationships:
          type: object
