Skip to content

Guide

Every list endpoint uses cursor-based pagination. No offset / page-number parameters — those break under concurrent inserts and don’t scale past a few thousand items.

Request shape

curl "https://api.esigkit.com/v1/orgs/$ORG_ID/users?limit=50&cursor=$CURSOR" \
  -H "Authorization: Bearer $ESIGKIT_TOKEN"
ParamDefaultMaxDescription
cursorOpaque base64url-encoded token returned by the previous page’s nextCursor. Don’t construct manually.
limit25100Page size. Values > 100 are clamped.

Response shape

{
  "items": [
    { "userId": "...", "email": "tyler@example.com", "...": "..." }
  ],
  "nextCursor": "eyJQSyI6Ik9SRyMwMDAwMC0wMDAwIi..."
}
FieldTypeMeaning
itemsarrayThe page’s items in their natural sort order (typically newest-first or insertion order).
nextCursorstring | nullToken for the next page. null means no more pages.

Loop pattern (Node)

async function listAllUsers(orgId: string): Promise<User[]> {
  const all: User[] = [];
  let cursor: string | null | undefined = undefined;

  do {
    const url = new URL(`https://api.esigkit.com/v1/orgs/${orgId}/users`);
    url.searchParams.set('limit', '100');
    if (cursor) url.searchParams.set('cursor', cursor);

    const res = await fetch(url, {
      headers: { Authorization: `Bearer ${process.env.ESIGKIT_TOKEN}` },
    });
    if (!res.ok) throw new Error(`list failed: ${res.status}`);

    const page = await res.json();
    all.push(...page.items);
    cursor = page.nextCursor;
  } while (cursor);

  return all;
}

Cursor opacity

The cursor is a base64url-encoded LastEvaluatedKey from DynamoDB. Don’t parse it. Don’t construct one manually. We may change the encoding without notice; the contract is “pass back what you got, get the next page.”

Invalid cursors return 400 BAD_REQUEST with error.code: BAD_REQUEST. If you stash a cursor and resume hours later, this can fire if the underlying key encoding changed — recover by starting over (omit cursor → start from the beginning).

Which endpoints paginate

  • GET /v1/orgs/{orgId}/users
  • GET /v1/orgs/{orgId}/templates
  • GET /v1/orgs/{orgId}/audit
  • GET /v1/orgs/{orgId}/api-keys
  • GET /v1/orgs/{orgId}/deploy/status

Single-resource GETs (GET /v1/orgs/{orgId}/users/{userId}) and small-aggregate reads (GET /v1/orgs/{orgId}/onboarding/checklist) don’t paginate.