Skip to content

Segment membership Read API #7408

@khvn26

Description

@khvn26

Scope

  • DRF endpoints:
    • GET /api/v1/segments/{id}/members?env={env_id}&cursor={ord}&limit={N}
    • GET /api/v1/segments/{id}/members/count?env={env_id}
    • GET /api/v1/segments/{id}/members/sample?env={env_id}&n={N}
  • Pagination caps: limit ≤ 200, n ≤ 100.
  • Warm-state surface on every response, derived from EnvironmentMembershipMetadata (Segment membership backfill lifecycle #7407):
    • is_warming: true when last_backfill_status="running".
    • as_of: last_backfill_completed_at (null while is_warming and no prior backfill exists).
  • RBAC: (VIEW_PROJECT or MANAGE_SEGMENTS) AND (VIEW_IDENTITIES or MANAGE_IDENTITIES).

Response schemas

Member item (shared by members and sample):

{
  "id": 12345,
  "identifier": "user-abc",
  "composite_key": "ser.abcDEF123_user-abc",
  "first_seen_at": "2026-04-01T12:00:00Z"
}

composite_key is {environment_api_key}_{identifier} and lets the frontend route to the edge identity detail page for Edge API envs without a DDB lookup at read time. For core envs the frontend continues to route by id.

GET /members — 200:

{
  "results": [<MemberItem>, ...],
  "next_cursor": "12500",
  "is_warming": false,
  "as_of": "2026-05-04T10:30:00Z"
}

next_cursor is null on the last page. is_warming and as_of follow the rules above.

GET /members/count — 200:

{
  "count": 42,
  "is_warming": false,
  "as_of": "2026-05-04T10:30:00Z"
}

GET /members/sample — 200:

{
  "results": [<MemberItem>, ...],
  "is_warming": false,
  "as_of": "2026-05-04T10:30:00Z"
}

results length is min(n, total_members). No pagination cursors — sample is one-shot.

Error responses use DRF's standard {"detail": "..."} shape. The 403 raised when VIEW_PROJECT is held but env VIEW_IDENTITIES is missing additionally carries "missing_permission": "VIEW_IDENTITIES" so the frontend can render the targeted empty state from #7412.

Acceptance criteria

  • 200 with empty results, is_warming=true, as_of=null when no atoms have been backfilled yet.
  • 200 with the prior bitmap's results, is_warming=true, and as_of set to the previous completion timestamp during a refresh.
  • 403 when VIEW_PROJECT is missing.
  • 403 with missing_permission="VIEW_IDENTITIES" when VIEW_PROJECT is held but env VIEW_IDENTITIES is missing.
  • Cursor-based pagination is stable across writes (no duplicates or missed identifiers within a page sequence). next_cursor is null on the last page.
  • Member items contain id, identifier, composite_key, first_seen_at only — no traits.

Metadata

Metadata

Assignees

No one assigned

    Labels

    apiIssue related to the REST API

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions