Skip to main content

POST /streams//records

Append one or more records atomically to a stream. Records are assigned sequential sequence numbers and timestamps upon successful append.

Authentication

Requires a valid access token with write permissions to the stream.

Path Parameters

stream
string
required
Stream name to append records to. Must be between 1 and 512 bytes in length.

Headers

S2-Basin
string
required
Basin name where the stream resides.
S2-Format
string
default:"base64"
Encoding format for record headers and body. Options:
  • base64 - Base64-encoded binary data (default)
  • utf8 - UTF-8 text
Content-Type
string
default:"application/json"
Request body format:
  • application/json - JSON format
  • application/protobuf - Protocol Buffers format
  • s2s/proto - S2S streaming protocol for bi-directional append
Accept
string
default:"application/json"
Response format:
  • application/json - JSON response
  • application/protobuf - Protobuf response

Request Body

records
array
required
Batch of records to append atomically. Must contain at least 1 and no more than 1000 records. The total size may not exceed 1 MiB of metered bytes.
match_seq_num
uint64
Optional conditional append. Enforces that the sequence number assigned to the first record matches this value. If not, the append fails with 412 Precondition Failed.
fencing_token
string
Optional fencing token for mutual exclusion. Must match the token previously set by a fence command record. If not, the append fails with 412 Precondition Failed.

Response

start
object
required
Position of the first appended record.
end
object
required
Position after the last appended record (exclusive).The difference between end.seq_num and start.seq_num equals the number of records appended.
tail
object
required
Current tail position of the stream.This can be greater than end if there were concurrent appends.

Status Codes

  • 200 OK - Records successfully appended
  • 400 Bad Request - Invalid request (e.g., empty batch, records too large)
  • 403 Forbidden - Insufficient permissions
  • 404 Not Found - Stream does not exist
  • 412 Precondition Failed - Conditional append failed (returns condition failure details)
  • 408 Request Timeout - Operation timed out
  • 409 Conflict - Stream is being deleted

Examples

Append a single record

curl -X POST https://mybasin.b.aws.s2.dev/v1/streams/events/records \
  -H "Authorization: Bearer $TOKEN" \
  -H "S2-Basin: mybasin" \
  -H "Content-Type: application/json" \
  -H "S2-Format: utf8" \
  -d '{
    "records": [
      {
        "body": "Hello, S2!",
        "headers": [["source", "api"]]
      }
    ]
  }'

Response

{
  "start": {
    "seq_num": 100,
    "timestamp": 1709481234567
  },
  "end": {
    "seq_num": 101,
    "timestamp": 1709481234567
  },
  "tail": {
    "seq_num": 101,
    "timestamp": 1709481234567
  }
}

Append multiple records with base64 encoding

curl -X POST https://mybasin.b.aws.s2.dev/v1/streams/logs/records \
  -H "Authorization: Bearer $TOKEN" \
  -H "S2-Basin: mybasin" \
  -H "Content-Type: application/json" \
  -H "S2-Format: base64" \
  -d '{
    "records": [
      {
        "timestamp": 1709481234567,
        "body": "SGVsbG8=",
        "headers": [["dHlwZQ==", "aW5mbw=="]]
      },
      {
        "timestamp": 1709481234568,
        "body": "V29ybGQ="
      }
    ]
  }'

Conditional append with sequence number check

curl -X POST https://mybasin.b.aws.s2.dev/v1/streams/events/records \
  -H "Authorization: Bearer $TOKEN" \
  -H "S2-Basin: mybasin" \
  -H "Content-Type: application/json" \
  -d '{
    "records": [{"body": "dGVzdA=="}],
    "match_seq_num": 100
  }'
If the tail is not at seq_num 100, you’ll receive:
// 412 Precondition Failed
{
  "seq_num_mismatch": 105
}

Fenced append

curl -X POST https://mybasin.b.aws.s2.dev/v1/streams/events/records \
  -H "Authorization: Bearer $TOKEN" \
  -H "S2-Basin: mybasin" \
  -H "Content-Type: application/json" \
  -d '{
    "records": [{"body": "ZmVuY2Vk"}],
    "fencing_token": "writer-123"
  }'

S2S Streaming Append

For high-throughput scenarios, use the S2S protocol with bi-directional streaming:
curl -X POST https://mybasin.b.aws.s2.dev/v1/streams/events/records \
  -H "Authorization: Bearer $TOKEN" \
  -H "S2-Basin: mybasin" \
  -H "Content-Type: s2s/proto" \
  -H "Accept-Encoding: zstd" \
  --data-binary @append-frames.bin
The S2S protocol uses length-prefixed protobuf frames with optional compression (zstd or gzip). Each frame contains an AppendInput message, and responses stream back AppendAck messages. See S2S Protocol for frame format details.

Notes

  • Records within a batch are appended atomically - either all succeed or all fail
  • Sequence numbers are strictly monotonic and have no gaps within a stream
  • Timestamps are monotonic but may have duplicates if client-specified
  • The total metered size includes headers and body but excludes protocol overhead
  • Empty records (no headers, no body) are valid but occupy a sequence number

Build docs developers (and LLMs) love