3 min readMay 15, 2026by maintainer

Access Grant API

Nexus Docs exposes an API path for external systems that need to grant documentation access.

Use it when another system already knows that a person should be allowed into the docs, for example:

  • A billing system after purchase
  • A license server after activation
  • A CRM or partner portal
  • A migration script importing users

The API is:

Text
POST /api/invitations

Despite the route name, it has two behaviors:

  1. If the user does not exist, it creates an invitation and returns an accept URL.
  2. If the user already exists, it grants permissions immediately and upgrades the user tier when the requested tier has a higher rank.

Authentication

API clients authenticate with x-api-key.

http
x-api-key: <INVITATION_API_KEY>

Configure the key in the environment:

env
INVITATION_API_KEY=generate-with-openssl-rand-base64-32

Admin users can call the same endpoint through the admin UI session. External systems should use the API key.

Request body

JSON
{
  "email": "[email protected]",
  "tier": "client",
  "extensions": ["nexus/customer-portal"],
  "message": "Your documentation access is ready.",
  "expiresInDays": 30
}
FieldRequiredPurpose
emailyesUser email address.
tiernoTier to grant. Defaults to client. Must exist in the tier registry.
extensionsnoProduct or extension grants used by client-tier access checks.
messagenoOptional invitation message.
expiresInDaysnoInvitation lifetime. Defaults to 30, maximum 365.

Curl example

Bash
curl -X POST "https://docs.example.com/api/invitations" \
  -H "Content-Type: application/json" \
  -H "x-api-key: $INVITATION_API_KEY" \
  -d '{
    "email": "[email protected]",
    "tier": "client",
    "extensions": ["nexus/customer-portal"],
    "message": "Your docs access is ready.",
    "expiresInDays": 30
  }'

New user response

When the email does not belong to an existing user, the API creates an invitation:

JSON
{
  "invitation": {
    "id": "clx...",
    "email": "[email protected]",
    "tier": "client",
    "extensions": ["nexus/customer-portal"],
    "expiresAt": "2026-06-14T00:00:00.000Z",
    "acceptUrl": "https://docs.example.com/auth/accept-invite?token=..."
  },
  "emailSent": true
}

If email delivery fails, the invitation is still created and the response includes an emailWarning. The caller can use acceptUrl to deliver the invitation manually.

Existing user response

When the email already belongs to a user, no invitation is created. Permissions are upserted and the user's tier is upgraded only when the requested tier rank is higher than their current tier rank.

JSON
{
  "status": "permissions_granted",
  "message": "User already exists. Permissions have been updated.",
  "userId": "clx..."
}

This makes repeated calls safe for the same user and extension list.

Tier behavior

The API validates tier against the configured tier registry.

Examples:

JSON
{ "tier": "client" }
{ "tier": "partner" }
{ "tier": "gold_partner" }

Rank controls whether a user is upgraded. The API does not downgrade users.

For client-rank users, extensions determines product-specific access. Higher tiers such as partner or admin bypass extension checks at render time.

Granting product access

Client-tier pages can be gated by extensions or by product.

If a page uses:

YAML
access_tier: client
product: nexus/customer-portal
extensions: []

then grant:

JSON
{
  "email": "[email protected]",
  "tier": "client",
  "extensions": ["nexus/customer-portal"]
}

If a page uses:

YAML
extensions: [nexus/customer-portal, nexus/reporting]

then granting either extension is enough for that page.

Error responses

StatusMeaning
400Invalid JSON, invalid body, or unknown tier.
403Missing or invalid API key, and no admin session.
201New invitation created.
200Existing user updated.

Security notes

  • Store INVITATION_API_KEY as a secret.
  • Send requests over HTTPS only.
  • Use product-specific extension grants for client-tier users.
  • Prefer higher tiers only for users who should bypass product checks.
  • Rotate the API key if it is exposed.
Access Grant API — Integrations | Nexus Docs