API Reference
Creddy exposes a REST API for credential management.
Base URL
http://localhost:8400/v1Authentication
Agent Authentication
Agent endpoints require a Bearer token. Creddy accepts two token types:
Vend Token (simple):
Authorization: Bearer ckr_abc123...OIDC JWT (standard OAuth):
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...Both provide the same access. See Authentication for details.
Admin Authentication
Admin endpoints (/v1/admin/*) require either:
- Local access — Requests from localhost are allowed without auth (for CLI)
- Admin-scoped agent — Agent with
admin:*scopes
Admin scopes:
| Scope | Endpoints |
|---|---|
admin:agents:read | GET /v1/admin/agents |
admin:agents:write | POST /v1/admin/agents, DELETE /v1/admin/agents/{name} |
admin:backends:read | GET /v1/admin/backends |
admin:backends:write | POST /v1/admin/backends, DELETE /v1/admin/backends/{name} |
admin:tokens:read | GET /v1/admin/tokens |
admin:tokens:write | DELETE /v1/admin/tokens/{id} |
admin:audit:read | GET /v1/admin/audit |
admin:enrollments:read | GET /v1/admin/pending |
admin:enrollments:write | POST /v1/admin/pending/{id}/* |
admin:plugins:write | POST /v1/admin/plugins/* |
admin:keys:read | GET /v1/admin/keys |
Wildcards work: admin:* grants all admin permissions, admin:agents:* grants read and write for agents.
OIDC Endpoints
Token Endpoint
Exchange client credentials for an access token.
POST /oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_id=agent_xxx&client_secret=cks_xxxResponse
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600
}Discovery Document
GET /.well-known/openid-configurationJWKS
GET /.well-known/jwks.jsonAgent Management (Admin)
List Agents
GET /v1/admin/agentsRequires: admin:agents:read
Response
[
{
"id": "ag_abc123",
"name": "my-agent",
"scopes": ["github:owner/repo"],
"created_at": "2024-01-15T15:00:00Z",
"last_used": "2024-01-15T16:30:00Z"
}
]Create Agent
POST /v1/admin/agentsRequires: admin:agents:write
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Agent name |
scopes | string[] | No | Allowed scopes |
expires_in | string | No | TTL (e.g., "4h", "24h") |
Example Request
curl -X POST http://creddy:8400/v1/admin/agents \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "task-runner",
"scopes": ["github:myorg/repo", "doppler:project"],
"expires_in": "4h"
}'Response
{
"id": "ag_abc123",
"name": "task-runner",
"token": "ckr_abc123...",
"scopes": ["github:myorg/repo", "doppler:project"],
"created_at": "2024-01-15T15:00:00Z",
"expires_at": "2024-01-15T19:00:00Z",
"oidc": {
"client_id": "agent_abc123def456",
"client_secret": "cks_abc123..."
},
"signing_key_id": "ABCD1234",
"signing_email": "task-runner@creddy.local"
}Note: token, oidc.client_secret, and signing keys are only shown once at creation.
Delete Agent
DELETE /v1/admin/agents/{name}Requires: admin:agents:write
Revokes all active credentials and deletes the agent.
Agent Self-Service
Get Status
GET /v1/statusReturns the authenticated agent’s info.
Response
{
"id": "ag_abc123",
"name": "my-agent",
"scopes": ["github:owner/repo"]
}Get Credential
Request a credential from a backend.
POST /v1/credentials/{backend}Response
{
"token": "gho_abc123...",
"expires_at": "2024-01-15T16:00:00Z"
}List Active Credentials
GET /v1/activeResponse
[
{
"id": "cred_abc123",
"backend": "github",
"expires_at": "2024-01-15T16:00:00Z",
"created_at": "2024-01-15T15:00:00Z"
}
]Revoke Credential
DELETE /v1/active/{id}Get Signing Key
GET /v1/signing-keyReturns the agent’s GPG signing key for git commits.
Response
{
"key_id": "ABCD1234",
"public_key": "-----BEGIN PGP PUBLIC KEY BLOCK-----...",
"private_key": "-----BEGIN PGP PRIVATE KEY BLOCK-----...",
"email": "my-agent@creddy.local",
"name": "my-agent"
}Self-Delete
Agent deletes itself when work is complete.
DELETE /v1/selfThis:
- Revokes all active backend credentials
- Deletes signing keys
- Deletes the agent
Returns 204 No Content on success.
Enrollment Endpoints
Initiate Enrollment
POST /v1/enrollNo authentication required.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Agent name |
scopes | string[] | No | Requested scopes |
Response
{
"enrollment_id": "enr_abc123",
"status": "pending",
"poll_url": "/v1/enroll/enr_abc123/status"
}Poll Enrollment Status
GET /v1/enroll/{id}/statusResponse (Pending)
{
"status": "pending"
}Response (Approved)
{
"status": "approved",
"token": "ckr_abc123...",
"scopes": ["github:read"]
}List Pending Enrollments (Admin)
GET /v1/admin/pendingRequires: admin:enrollments:read
Approve Enrollment (Admin)
POST /v1/admin/pending/{id}/approveRequires: admin:enrollments:write
Request Body (optional)
| Field | Type | Description |
|---|---|---|
scopes | string[] | Override requested scopes |
Reject Enrollment (Admin)
POST /v1/admin/pending/{id}/rejectRequires: admin:enrollments:write
Backend Management (Admin)
List Backends
GET /v1/admin/backendsRequires: admin:backends:read
Create Backend
POST /v1/admin/backendsRequires: admin:backends:write
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Backend type (github, doppler, etc.) |
name | string | No | Custom name (defaults to type) |
config | object | Yes | Backend-specific configuration |
Delete Backend
DELETE /v1/admin/backends/{name}Requires: admin:backends:write
Token Management (Admin)
List All Active Tokens
GET /v1/admin/tokensRequires: admin:tokens:read
Query Parameters
| Parameter | Description |
|---|---|
backend | Filter by backend |
agent | Filter by agent name |
Revoke Token
DELETE /v1/admin/tokens/{id}Requires: admin:tokens:write
Audit Log (Admin)
GET /v1/admin/auditRequires: admin:audit:read
Query Parameters
| Parameter | Description |
|---|---|
limit | Max results (default 100) |
agent_id | Filter by agent ID |
action | Filter by action type |
Health Check
GET /healthNo authentication required.
{
"status": "ok"
}Error Responses
{
"error": "description of what went wrong"
}| HTTP Status | Meaning |
|---|---|
| 400 | Bad request (invalid parameters) |
| 401 | Missing or invalid authentication |
| 403 | Insufficient permissions |
| 404 | Resource not found |
| 500 | Server error |