Skip to content

REST API

Grant exposes a full REST API at /api/* with interactive Swagger documentation. All endpoints use JSON and follow consistent request/response patterns.

Swagger UI

The API ships with an interactive Swagger UI for exploring and testing every endpoint:

ResourceURL
Swagger UIhttp://localhost:4000/api-docs
OpenAPI JSONhttp://localhost:4000/api-docs.json

Swagger UI includes request/response schemas, example payloads, and a "Try it out" button for every endpoint. The OpenAPI spec can be imported into Postman, Insomnia, or used to generate client SDKs.

Authenticating in Swagger UI

Most endpoints require a JWT. Follow these steps to authenticate in the Swagger UI:

1. Get a token — Expand POST /api/auth/login under the Authentication tag, click "Try it out", and send:

json
{
  "provider": "email",
  "providerId": "admin@example.com",
  "providerData": { "password": "YourPassword1!" }
}

2. Copy the token — From the response, copy the accessToken value.

3. Authorize — Click the Authorize button (lock icon) at the top of the page, paste the token into the bearerAuth field (without the Bearer prefix), and click Authorize.

4. Test endpoints — All subsequent "Try it out" requests will include the token automatically.

Persist Authorization

Swagger UI is configured with persistAuthorization: true — your token survives page reloads until you click Logout in the Authorize dialog.

Base URL

http://localhost:4000/api

For production deployments, replace with your deployed API URL.

Authentication

Include a JWT access token in the Authorization header:

http
Authorization: Bearer <accessToken>

Obtain tokens via POST /api/auth/login (email/password) or POST /api/auth/register (new account). Refresh expired tokens with POST /api/auth/refresh.

Authentication Flow

bash
# 1. Login
curl -s -X POST http://localhost:4000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"provider":"email","providerId":"admin@example.com","providerData":{"password":"YourPassword1!"}}'

# Response: { "success": true, "data": { "accessToken": "eyJ...", "refreshToken": "eyJ...", "accounts": [...] } }

# 2. Use the token
curl -s http://localhost:4000/api/organizations \
  -H "Authorization: Bearer <accessToken>" \
  -H "Content-Type: application/json"

# 3. Refresh when expired
curl -s -X POST http://localhost:4000/api/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{"accessToken":"<expired>","refreshToken":"<refreshToken>"}'

Endpoints by Tag

Every endpoint is fully documented in the Swagger UI. The table below links to each tag for quick navigation:

TagEndpointsDescription
Authentication10Login, register, refresh, logout, OAuth, token exchange, authorization check
Me11Profile, sessions, password, auth methods, data export, picture upload
Organizations5CRUD for organizations
Organization Invitations7Invite, accept, resend, renew, revoke
Organization Members3List, update role, remove
Projects4CRUD for projects
Users5CRUD for users within a scope
Roles4CRUD for roles
Groups4CRUD for groups (permission bundles)
Permissions4CRUD for permissions
Resources4CRUD for resources (RBAC targets)
API Keys5Create, list, revoke, delete, token exchange
Tags4CRUD for tags

REST-Only Endpoints

Some operations are only available via REST (not GraphQL):

  • GET /api/auth/github — Initiate GitHub OAuth (browser redirect)
  • GET /api/auth/github/callback — GitHub OAuth callback
  • POST /api/auth/cli-callback — Exchange CLI one-time code for tokens
  • POST /api/auth/token — Exchange API key for JWT
  • POST /api/auth/is-authorized — Check authorization (used by SDKs)
  • GET /api/me/export — GDPR data export (file download)
  • GET /.well-known/jwks.json — JWKS public key discovery (3 scoped variants)

See Transport Layers for a full comparison.

Scoping and Multi-Tenancy

Most endpoints require a scope to specify the tenant context. The scope is passed differently depending on the HTTP method:

GET / DELETE — Query parameters:

bash
GET /api/roles?scopeId=<orgId>:<projectId>&tenant=organizationProject

POST / PATCH — Request body:

json
{
  "name": "Editor",
  "scope": { "tenant": "organizationProject", "id": "<orgId>:<projectId>" }
}

The tenant field indicates the level of the hierarchy. The id field is either a single UUID or two UUIDs joined by : (e.g., orgId:projectId).

TenantScope ID formatExample
account<accountId>Personal account scope
organization<orgId>Organization scope
accountProject<accountId>:<projectId>Personal project
organizationProject<orgId>:<projectId>Org project

TIP

See Multi-Tenancy for details on tenant isolation and the hierarchy model.

Response Format

Success:

json
{
  "success": true,
  "data": { ... }
}

Error:

json
{
  "error": "Localized error message",
  "code": "ERROR_CODE"
}

See Error Handling for the full error reference.

Field Selection

Load related entities on-demand with the relations query parameter:

bash
GET /api/roles?scopeId=...&tenant=organizationProject&relations=groups,tags

Only base fields are returned by default. See Field Selection for available relations per resource.

Rate Limiting

Rate limits are configurable via environment variables (SECURITY_RATE_LIMIT_*). Auth endpoints have stricter limits than general endpoints. When a limit is exceeded, the API returns 429 Too Many Requests with a Retry-After header. See Configuration for details.


Related:

Released under the MIT License.