Skip to content

API reference: overview

The TwistCue Admin API is a NestJS service exposing REST endpoints under /v1/admin/*. All admin endpoints are protected by AdminJwtGuard + PermissionsGuard.

  • Dev: http://localhost:3000/v1
  • Staging/Prod: https://api.twistcue.connectorme.com/v1 (subject to change)
  • Prefix /v1. New majors introduced when breaking mobile contracts.
  • Admin endpoints under /v1/admin/*. Public endpoints under /v1/* (e.g. /v1/feed, /v1/flags).
  • Login: POST /v1/admin/auth/login → returns {access_token, admin}.
  • Token is a JWT with sub, role, permissions[], token_version, exp (12h).
  • Send on subsequent requests as:
    • HTTP header: Authorization: Bearer <token> or
    • Cookie: tc_admin_token=<token> (set automatically on login response).

Every admin endpoint declares required permissions via @RequirePermission('resource:action', ...). The PermissionsGuard:

  • Reads req.admin.permissions from the JWT.
  • Runs OR semantics across the declared perms.
  • Returns 403 insufficient_permissions with { required: [...] } on failure.
  • * in the granted list short-circuits to allow.

Standard error shape:

{
"statusCode": 403,
"error": "insufficient_permissions",
"required": ["catalog:write"]
}

Common error codes:

CodeHTTPMeaning
invalid_credentials401Bad email/password.
token_expired / token_invalid401JWT rejected.
admin_disabled403Admin is_active=false.
insufficient_permissions403Permission check failed.
approver_must_differ403Two-person rule violated.
support_daily_cap_exceeded400500-coin support cap.
insufficient_balance400Coin deduct would go negative.
invalid_transition400Publish state machine rejects the move.
in_use409Delete refused because references exist.
not_found404Standard.
  • JSON, camelCase.
  • UTC ISO-8601 for datetimes.
  • cents for money, coins (integer) for coin values (1 coin = $0.01).
  • Cursor pagination: ?cursor=<opaque>&limit=<int>. Response includes nextCursor: string | null.
  • All mutating endpoints are idempotent-safe where they can be (server dedup on client_dedup_key for events) but do NOT guarantee full idempotency: client should retry cautiously.
  • Login endpoint: 10 attempts / 5 min / IP.
  • Other admin endpoints: 300 req / min / admin (generous: this is an operator surface).
  • CSV export streaming does not count against the rate limit.
  • Every mutating endpoint writes an AuditLog row in the same transaction.
  • Reads are not audited (too high volume).

Read the section that matches the module you’re calling: