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

> Append a batch of records atomically to an S2 stream, with optional append conditions.

# Append records.

<CardGroup cols={3}>
  <Card title="Append concepts" icon="pen" href="/concepts/appends">
    Understand append acknowledgements, batching, and durability.
  </Card>

  <Card title="Concurrency control" icon="sliders" href="/concepts/concurrency-control">
    Coordinate writers with match sequence numbers and fencing tokens.
  </Card>

  <Card title="Appending SDK" icon="code" href="/sdk/appending">
    Use append sessions, the Producer API, batching, and backpressure.
  </Card>
</CardGroup>


## OpenAPI

````yaml post /streams/{stream}/records
openapi: 3.1.0
info:
  title: S2, the durable streams API
  description: Streams as a cloud storage primitive.
  termsOfService: https://s2.dev/terms
  contact:
    email: support@s2.dev
  license:
    name: MIT
  version: 1.0.0
servers:
  - url: https://aws.s2.dev/v1
security:
  - access_token: []
tags:
  - name: metrics
    description: Usage metrics and data.
  - name: basins
    description: Manage basins
  - name: access-tokens
    description: Manage access tokens
  - name: locations
    description: Manage locations
  - name: streams
    description: Manage streams
  - name: records
    description: Manage records
paths:
  /streams/{stream}/records:
    servers:
      - url: https://{basin}.b.s2.dev/v1
        description: Endpoint for the basin
        variables:
          basin:
            default: ''
            description: Basin name
    post:
      tags:
        - records
      summary: Append records.
      operationId: append
      parameters:
        - name: stream
          in: path
          description: Stream name.
          required: true
          schema:
            $ref: '#/components/schemas/StreamNameStr'
        - name: s2-format
          in: header
          description: >-
            Defines the interpretation of record data (header name, header
            value, and body) with the JSON content type.

            Use `raw` (default) for efficient transmission and storage of
            Unicode data — storage will be in UTF-8.

            Use `base64` for safe transmission with efficient storage of binary
            data.
          required: false
          schema:
            $ref: '#/components/schemas/Format'
        - name: s2-encryption-key
          in: header
          description: |-
            Encryption key material for append and read operations.
            Provide base64-encoded key when stream encryption is enabled.
          required: false
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AppendInput'
        required: true
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AppendAck'
        '400':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorInfo'
        '403':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorInfo'
        '404':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorInfo'
        '408':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorInfo'
        '409':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorInfo'
        '412':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AppendConditionFailed'
components:
  schemas:
    StreamNameStr:
      type: string
      maxLength: 512
      minLength: 1
    Format:
      type: string
      enum:
        - raw
        - base64
    AppendInput:
      type: object
      description: Payload of an `append` request.
      required:
        - records
      properties:
        fencing_token:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/FencingToken'
              description: >-
                Enforce a fencing token, which starts out as an empty string
                that can be overridden by a `fence` command record.
        match_seq_num:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/u64'
              description: >-
                Enforce that the sequence number assigned to the first record
                matches.
        records:
          type: array
          items:
            $ref: '#/components/schemas/AppendRecord'
          description: >-
            Batch of records to append atomically, which must contain at least
            one record, and no more than 1000.

            The total size of a batch of records may not exceed 1 MiB of metered
            bytes.
    AppendAck:
      type: object
      description: Success response to an `append` request.
      required:
        - start
        - end
        - tail
      properties:
        end:
          $ref: '#/components/schemas/StreamPosition'
          description: >-
            Sequence number of the last record that was appended `+ 1`, and
            timestamp of the last record that was appended.

            The difference between `end.seq_num` and `start.seq_num` will be the
            number of records appended.
        start:
          $ref: '#/components/schemas/StreamPosition'
          description: Sequence number and timestamp of the first record that was appended.
        tail:
          $ref: '#/components/schemas/StreamPosition'
          description: >-
            Sequence number that will be assigned to the next record on the
            stream, and timestamp of the last record on the stream.

            This can be greater than the `end` position in case of concurrent
            appends.
    ErrorInfo:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: string
        message:
          type: string
    AppendConditionFailed:
      oneOf:
        - type: object
          title: fencing token
          description: |-
            Fencing token did not match.
            The expected fencing token is returned.
          required:
            - fencing_token_mismatch
          properties:
            fencing_token_mismatch:
              $ref: '#/components/schemas/FencingToken'
              description: |-
                Fencing token did not match.
                The expected fencing token is returned.
        - type: object
          title: seq num
          description: |-
            Sequence number did not match the tail of the stream.
            The expected next sequence number is returned.
          required:
            - seq_num_mismatch
          properties:
            seq_num_mismatch:
              $ref: '#/components/schemas/u64'
              description: |-
                Sequence number did not match the tail of the stream.
                The expected next sequence number is returned.
      description: Aborted due to a failed condition.
    FencingToken:
      type: string
      maxLength: 36
    u64:
      type: integer
      format: int64
      minimum: 0
    AppendRecord:
      type: object
      description: Record to be appended to a stream.
      properties:
        body:
          type: string
          description: Body of the record.
        headers:
          type: array
          items:
            $ref: '#/components/schemas/Header'
          description: Series of name-value pairs for this record.
        timestamp:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/u64'
              description: >-
                Timestamp for this record.

                The service will always ensure monotonicity by adjusting it up
                if necessary to the maximum observed timestamp.

                Refer to stream timestamping configuration for the finer
                semantics around whether a client-specified timestamp is
                required, and whether it will be capped at the arrival time.
    StreamPosition:
      type: object
      description: Position of a record in a stream.
      required:
        - seq_num
        - timestamp
      properties:
        seq_num:
          $ref: '#/components/schemas/u64'
          description: Sequence number assigned by the service.
        timestamp:
          $ref: '#/components/schemas/u64'
          description: >-
            Timestamp, which may be client-specified or assigned by the service.

            If it is assigned by the service, it will represent milliseconds
            since Unix epoch.
    Header:
      type: array
      items:
        type: string
      maxItems: 2
      minItems: 2
  securitySchemes:
    access_token:
      type: http
      scheme: bearer
      description: >-
        Bearer authentication header of the form `Bearer <token>`, where
        `<token>` is your access token.

````