Personal Access Token (PAT) for API Access
A Personal Access Token (PAT) is a pass issued as an opaque, revocable token (cpat-...) instead of a signed JWT. It is the recommended Access Pass method for authorizing service-to-service and partner API calls.
Why use a PAT instead of a JWT
| JWT access token | PAT (cpat-...) | |
|---|---|---|
| Validation | Signature check, mostly local/offline | Introspection call to cidaas at request time |
| Revocation | Only takes effect after expiry, unless actively checked | Immediately revocable — checked on every request |
| Binding | Scopes and claims baked into the token | Scopes, validity, and optional resource constraints are enforced centrally and can be changed without reissuing the token |
Choose a PAT when you need:
- Revocable, opaque tokens for long-lived service integrations (e.g. partner APIs).
- Central, real-time checks of active status and scopes.
- Optional token-to-API binding via
targetResourceRefwhen scopes alone are not enough to distinguish which service a token may call.
How it works
Step 1: Create a PAT-enabled pass template
Most PAT integrations only need scopes — no Resource Catalog registration required.
POST /accesspass-srv/templates
{
"name": "partner-api-pat-template",
"description": "PAT template for partner API access",
"methods": ["pat"],
"maxValidity": {
"value": 30,
"unit": "days"
},
"systemConstraint": {
"scopes": ["analytics:read", "incident:write"]
}
}
See Create pass template.
Step 2: Issue the pass and receive the token
POST /accesspass-srv/passes
{
"passUserHolder": { "sub": "sub-partner-admin-01", "givenName": "Neha", "familyName": "Iyer" },
"passUser": { "sub": "sub-partner-admin-01", "givenName": "Neha", "familyName": "Iyer" },
"pass": {
"title": "Partner API PAT",
"passId": "PARTNER-PAT-0001",
"productId": "partner-api",
"productName": "Partner API",
"productInstanceId": "partner-api-v1",
"passTemplateId": "partner-api-pat-template",
"method": "pat",
"validFrom": "2026-03-20T09:00:00Z",
"validTo": "2026-04-19T09:00:00Z",
"systemConstraint": { "scopes": ["analytics:read", "incident:write"] }
}
}
The response contains the opaque token:
{
"success": true,
"data": {
"passId": "PARTNER-PAT-0001",
"token": "cpat-<opaque-token>"
}
}
Store this token securely on the partner/service side — it is not a JWT and cannot be decoded or introspected offline. See Create a new pass.
Step 3: Validate the PAT on every API request
Client applications call your protected API with Authorization: Bearer cpat-.... Your API introspects the token on each request rather than validating a signature locally:
POST /accesspass-srv/passes/pat/introspect
{
"token": "cpat-<opaque-token>",
"access_method": "pat",
"strictValidation": true,
"systemFields": { "scopes": ["analytics:read"] }
}
See Introspect (validate) a pass. A response with active: true and matching scopes authorizes the request.
Integrating introspection in your API (Go example)
If your service is built with Fiber and the cidaas go-interceptor library, use the PAT interceptor to enforce introspection-based checks per route. Deployments may also use the internal GitLab module (cidaas-go-interceptor/v4); confirm the package path for your environment.
patInterceptor, err := cidaasinterceptor.NewPatInterceptor(cidaasinterceptor.Options{
BaseURI: "https://<your-cidaas-domain>",
ClientID: "<api-client-id>",
})
app := fiber.New()
app.Get("/analytics",
patInterceptor.VerifyTokenByIntrospect(cidaasinterceptor.SecurityOptions{
Scopes: []string{"analytics:read"},
}),
handler,
)
If you are not using Go/Fiber, call the introspection endpoint directly from your own middleware before processing the request.
Step 4: Revoke a PAT
Because a PAT is checked by introspection on every request, revoking it takes effect immediately — no need to wait for expiry. Revoke it the same way as any other pass:
POST /accesspass-srv/passes/revoke
{
"passId": "PARTNER-PAT-0001",
"reason": "Partner integration decommissioned"
}
See Revoke a pass.
Related APIs
Endpoints used in this guide. For the full API surface, see the Access Pass API reference.
| Operation | Method | Path | Description | Link |
|---|---|---|---|---|
| Create pass template | POST | /accesspass-srv/templates | PAT-enabled template with methods: ["pat"]. | View API |
| Create pass | POST | /accesspass-srv/passes | Issues the pass and returns the cpat-... token. | View API |
| Introspect pass | POST | /accesspass-srv/passes/pat/introspect | Validates the token on each API request. | View API |
| Revoke pass | POST | /accesspass-srv/passes/revoke | Immediately revokes the PAT. | View API |
Optional: Bind the PAT to specific APIs (targetResourceRef)
Use this only when a token must be limited to specific catalog entries beyond scopes — for example, two APIs share the same scope but should accept different tokens.
- Register the APIs as catalog resources first — see Step 1 in Physical access control (managed via the Access Control service / Trustdesk, not
accesspass-srv). - Add
targetResourceRefto the template, pass, and introspection request.
Template variant:
POST /accesspass-srv/templates
{
"name": "partner-api-pat-template",
"description": "PAT template scoped to Analytics API",
"methods": ["pat"],
"maxValidity": { "value": 30, "unit": "days" },
"systemConstraint": { "scopes": ["analytics:read", "incident:write"] },
"targetResourceRef": {
"resourceIds": ["api-analytics-v1"],
"resourceGroupIds": ["group:partner-apis"]
}
}
Pass variant — add to the pass object:
"targetResourceRef": { "resourceIds": ["api-analytics-v1"] }
Introspection variant — include targetResourceRef in the introspect body only when the pass or template defines it:
POST /accesspass-srv/passes/pat/introspect
{
"token": "cpat-<opaque-token>",
"access_method": "pat",
"strictValidation": true,
"systemFields": { "scopes": ["analytics:read"] },
"targetResourceRef": { "resourceIds": ["api-analytics-v1"] }
}
Checklist
- Use
method: "pat"on the template and pass instead ofqrcodeor other presentation methods. - Scope the PAT with
systemConstraint.scopes— this is the primary access control for most integrations. - Add
targetResourceRefonly when you need to restrict which API/service the token works against beyond scopes. - Never expect to decode a PAT locally — always validate it via
POST /accesspass-srv/passes/pat/introspect. - Revoke a PAT immediately when an integration ends; there is no need to wait for
validTo.