Personal Access Tokens
Personal Access Tokens (PATs) provide secure API access for users to integrate with the Manager programmatically without using their primary credentials.
Overview
PATs are user-scoped tokens that allow:
- API Authentication - Access GraphQL and REST APIs programmatically
- Script Automation - Automate workflows with CLI tools or scripts
- CI/CD Integration - Deploy and manage resources from CI/CD pipelines
- Third-party Tools - Integrate with external tools and services
Security Features
PBKDF2 Hashing
PATs are hashed using PBKDF2 (Password-Based Key Derivation Function 2) following OWASP 2023 recommendations:
- 600,000 iterations - Computational cost to prevent brute-force attacks
- SHA-256 hash function
- Unique salt per token
- Only the hash is stored - plaintext token never persisted
Token Prefix
The first few characters of each token are stored for searchability without compromising security. This allows you to identify tokens in the UI without exposing the full value.
Example: pfy_abc123... → Prefix pfy_abc is searchable
Creating a Personal Access Token
Via UI
- Navigate to Settings → Personal Access Tokens
- Click Create Token
- Fill in token details:
- Name - Descriptive name (e.g., "GitHub Actions", "CLI Tool")
- Expires At - Optional expiration date
- Click Create
- Copy the token immediately - it will only be shown once
IMPORTANT
The token is displayed only once during creation. Store it securely - you cannot retrieve it later.
Via API
mutation {
createPersonalAccessToken(
name: "GitHub Actions Deployment"
expiresAt: "2025-12-31T23:59:59Z"
) {
token
personalAccessToken {
id
name
createdAt
expiresAt
}
}
}Response:
{
"data": {
"createPersonalAccessToken": {
"token": "pfy_abc123def456ghi789...",
"personalAccessToken": {
"id": "uuid",
"name": "GitHub Actions Deployment",
"createdAt": "2025-12-01T10:00:00Z",
"expiresAt": "2025-12-31T23:59:59Z"
}
}
}
}Using Personal Access Tokens
HTTP Authentication
Include the token in the Authorization header:
curl -H "Authorization: Bearer pfy_abc123def456ghi789..." \
https://manager.example.com/queryGraphQL Client
import { createClient } from "@urql/core";
const client = createClient({
url: "https://manager.example.com/query",
fetchOptions: {
headers: {
Authorization: `Bearer ${process.env.PAT_TOKEN}`,
},
},
});CLI Tools
export PRODUCTIFY_TOKEN="pfy_abc123def456ghi789..."
# Use in commands
pfy projects list --token $PRODUCTIFY_TOKENManaging Tokens
Listing Your Tokens
Via UI: Navigate to Settings → Personal Access Tokens to view all your tokens.
Via API:
query {
myPersonalAccessTokens(
filters: []
order: { field: "created_at", direction: DESC }
pagination: { limit: 20, offset: 0 }
) {
id
name
tokenPrefix
createdAt
expiresAt
revokedAt
lastUsedAt
}
}Revoking a Token
Revoking a token immediately prevents it from being used for authentication.
Via UI:
- Navigate to Settings → Personal Access Tokens
- Find the token to revoke
- Click Revoke
- Confirm the action
Via API:
mutation {
revokePersonalAccessToken(id: "token-uuid") {
id
revokedAt
}
}TIP
Revoked tokens are not deleted but marked as revoked. This preserves audit history.
Deleting a Token
Deleting permanently removes the token record.
Via UI:
- Navigate to Settings → Personal Access Tokens
- Find the token to delete
- Click Delete
- Confirm the action
Via API:
mutation {
deletePersonalAccessToken(id: "token-uuid")
}Token Expiration
Setting Expiration
When creating a token, you can optionally set an expiration date:
mutation {
createPersonalAccessToken(
name: "Temporary Token"
expiresAt: "2025-12-31T23:59:59Z"
) {
token
personalAccessToken {
expiresAt
}
}
}No Expiration
Tokens without an expiration date remain valid indefinitely until revoked or deleted.
Use cases for non-expiring tokens:
- Long-running services
- Internal automation
- Development environments
Use cases for expiring tokens:
- Temporary access grants
- External contractors
- Security compliance requirements
Best Practices
Security
- Store tokens securely - Use environment variables or secret managers
- Never commit tokens to version control
- Set expiration dates for tokens that don't need indefinite access
- Revoke unused tokens - Clean up tokens that are no longer needed
- Use descriptive names - Make it easy to identify token purpose
- Rotate tokens regularly - Create new tokens and revoke old ones periodically
Organization
- One token per use case - Create separate tokens for different tools/scripts
- Name tokens clearly - Use names that indicate purpose and location (e.g., "Production CI/CD", "Development CLI")
- Document token usage - Keep records of what each token is used for
- Monitor token usage - Check
lastUsedAtto identify unused tokens
Operational
- Test tokens after creation - Verify tokens work before deploying to production
- Have a rotation plan - Regularly create new tokens and retire old ones
- Alert on expiration - Monitor tokens approaching expiration
- Coordinate revocation - Plan token revocation to avoid service disruptions
Troubleshooting
Token Not Working
Check:
- Token hasn't expired (
expiresAt) - Token hasn't been revoked (
revokedAt) - Token is correctly formatted in the
Authorizationheader - Token includes the
Bearerprefix in the header - Network connectivity to Manager API
Authentication Failures
Verify:
- Authorization header format:
Authorization: Bearer <token> - Token string is complete and unmodified
- Token belongs to the user making the request
- User account is active and not disabled
Token Not Found
Possible causes:
- Token was deleted
- Token belongs to different user
- Token ID is incorrect
- Database connectivity issues
Comparison with Machine Users
| Feature | Personal Access Tokens | Machine Users |
|---|---|---|
| Scope | User-level | Tenant-level |
| Purpose | Personal automation | Service authentication |
| Expiration | Optional | No expiration |
| Authentication | Bearer only | Bearer or Basic |
| Use Case | CLI tools, scripts | Backend services |
| Created By | Individual users | Administrators |
When to use PATs:
- Personal automation and scripts
- CLI tool authentication
- Development and testing
- User-specific integrations
When to use Machine Users:
- Production backend services
- Service-to-service communication
- Tenant-scoped operations
- Long-running services
See Machine Users for service account authentication.
API Reference
Complete PAT management via GraphQL API:
# List tokens
query {
myPersonalAccessTokens(
filters: []
order: { field: "created_at", direction: DESC }
pagination: { limit: 20, offset: 0 }
) {
id
name
tokenPrefix
createdAt
expiresAt
lastUsedAt
}
}
# Create token
mutation {
createPersonalAccessToken(
name: "New Token"
expiresAt: "2025-12-31T23:59:59Z"
) {
token
personalAccessToken {
id
name
}
}
}
# Revoke token
mutation {
revokePersonalAccessToken(id: "token-uuid") {
id
revokedAt
}
}
# Delete token
mutation {
deletePersonalAccessToken(id: "token-uuid")
}See the full API Reference for details.