Authentication & Authorization
Dagy supports multiple authentication methods and enforces role-based access control (RBAC) on all API endpoints.
Authentication Methods
1. Access Tokens (Default)
Access tokens are issued via POST /auth/login and stored with a configurable TTL.
Obtaining a token:
curl -X POST https://api.dagy.io/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com"}'
Response:
{
"access_token": "dagy_at_a1b2c3d4...",
"token_type": "Bearer",
"expires_at": 1738723200
}
Using the token:
curl https://api.dagy.io/flows \
-H "Authorization: Bearer dagy_at_a1b2c3d4..."
Configuration:
| Environment Variable | Description | Default |
|---|---|---|
DAGY_USERS | Users table name | - |
DAGY_ACCESS_TOKENS | Access tokens table name | - |
DAGY_ACCESS_LOGS | Access logs table (optional audit) | - |
DAGY_ACCESS_TOKEN_TTL_SECONDS | Token lifetime | 86400 (24h) |
Tokens are stored locally by the CLI at ~/.dagy/credentials.
2. API Keys
API keys provide programmatic access with scoped permissions. They are created via POST /api-keys and identified by a dagy_ prefix.
Creating an API key:
curl -X POST https://api.dagy.io/api-keys \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"name": "CI Pipeline", "scopes": ["flows.read", "runs.trigger"]}'
The full API key is returned only once in the creation response. Store it securely.
Using an API key:
curl https://api.dagy.io/runs \
-H "Authorization: Bearer dagy_sk_x1y2z3..."
Key features:
- SHA-256 hashed at rest (only the
key_prefixis stored for display) - Scoped permissions: keys with explicit scopes are restricted to those permissions
- Keys with no scopes default to full owner access
- Managed via
POST /api-keys,GET /api-keys,DELETE /api-keys/{key_id}
3. JWT Authentication (Optional)
When enabled, the API validates JSON Web Tokens against a JWKS endpoint. This integrates with identity providers like Clerk, Auth0, or Okta.
Configuration:
| Environment Variable | Description |
|---|---|
DAGY_JWT_REQUIRED | Set to true to require JWT auth |
DAGY_JWT_ISSUER | Expected iss claim value |
DAGY_JWT_AUDIENCE | Expected aud claim value |
DAGY_JWKS_URL | URL to the JWKS key set |
Using JWT:
curl https://api.dagy.io/flows \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."
Fallback Behavior
If JWT is disabled and access-token tables are not configured, the API runs in development mode: all requests are accepted with a default identity (org_id: "default", role: "owner").
Role-Based Access Control (RBAC)
Every authenticated request resolves to an identity with an organization role. Dagy enforces a static permission matrix with 4 roles and 22 granular permissions.
Permission Matrix
| Permission | Owner | Admin | Developer | Viewer |
|---|---|---|---|---|
flows.read | Yes | Yes | Yes | Yes |
flows.write | Yes | Yes | Yes | - |
flows.delete | Yes | Yes | - | - |
runs.read | Yes | Yes | Yes | Yes |
runs.trigger | Yes | Yes | Yes | - |
runs.cancel | Yes | Yes | Yes | - |
schedules.read | Yes | Yes | Yes | Yes |
schedules.write | Yes | Yes | Yes | - |
secrets.read | Yes | Yes | - | - |
secrets.write | Yes | Yes | - | - |
admin.members | Yes | Yes | - | - |
admin.org | Yes | - | - | - |
admin.api_keys | Yes | Yes | - | - |
admin.audit | Yes | Yes | - | - |
billing.read | Yes | Yes | Yes | Yes |
billing.write | Yes | - | - | - |
environments.read | Yes | Yes | Yes | Yes |
environments.write | Yes | Yes | Yes | - |
notifications.read | Yes | Yes | Yes | Yes |
notifications.write | Yes | Yes | Yes | - |
sensors.read | Yes | Yes | Yes | Yes |
sensors.write | Yes | Yes | Yes | - |
How Permission Checks Work
Each endpoint calls require_permission(identity, "permission.name") before executing business logic. If the user's role lacks the required permission, the API returns:
HTTP 403 Forbidden
{
"detail": "Permission denied: flows.write required"
}
Managing Roles
View the permission matrix:
curl https://api.dagy.io/orgs/{org_id}/roles \
-H "Authorization: Bearer <token>"
Change a member's role:
curl -X PATCH https://api.dagy.io/orgs/{org_id}/members/user@example.com/role \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"role": "developer"}'
Role changes are audit-logged automatically.
Super Admin
In addition to org-scoped RBAC roles, Dagy has a super admin flag: a platform-level boolean on the user record that is separate from the 4 organization roles. Super admins can perform cross-org administrative operations that are not available to any org-scoped role.
How It Works
The super_admin field is a boolean stored on the user record. When a request hits a super-admin-gated endpoint, the API calls require_super_admin(identity), which checks identity["super_admin"]. If the flag is not true, the API returns:
HTTP 403 Forbidden
{
"detail": "Super admin access required"
}
Super admin status is not granted through org membership or role assignment; it must be set directly on the user record in the database.
Capabilities
Super admins have access to 16 endpoints across three categories:
Customer Management (/admin/customers/*):
- List, view, and update customer organizations
- View customer members, usage, audit logs, and sessions
- Suspend and reactivate organizations
- Adjust credit balances
- Revoke user sessions
Exception Trace Management (/admin/exceptions/*):
- List and view exception traces across all organizations
- Download trace files (requires
s3:DeleteObjectIAM permission for deletion) - Delete exception traces
Organization Impersonation (/admin/impersonate/{org_id}):
- Impersonate any customer organization with owner-level access
- Sets the
X-Impersonate-Orgheader context for subsequent requests - All impersonation actions are audit-logged
See the Super Admin API Reference for full endpoint documentation.
Key Differences from RBAC Roles
| Aspect | RBAC Roles | Super Admin |
|---|---|---|
| Scope | Per-organization | Platform-wide |
| Assignment | Via org membership | Direct user record flag |
| Roles | Owner, Admin, Developer, Viewer | Boolean (true/false) |
| Endpoints | Org-scoped resources | Cross-org admin operations |
Audit Logging
All authentication and authorization events are tracked:
- Access token creation and usage (via access logs)
- API key creation and deletion
- Role changes
- Permission denial events
- All mutation operations across all endpoints
Query the audit trail via GET /audit-logs (requires admin.audit permission).
Security Best Practices
- Rotate API keys regularly: Delete old keys and create new ones
- Use scoped API keys: Grant only the permissions each integration needs
- Enable JWT for production: Use a proper identity provider instead of access tokens
- Monitor audit logs: Review authentication events for anomalies
- Use HTTPS: All API communication should be encrypted in transit
- Store secrets securely: Use Dagy's built-in encrypted secret management instead of environment variables for sensitive configuration