Skip to Content
ReferenceAPI

API Reference

Creddy exposes a REST API for credential management.

Base URL

http://localhost:8400/v1

Authentication

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:

  1. Local access — Requests from localhost are allowed without auth (for CLI)
  2. Admin-scoped agent — Agent with admin:* scopes

Admin scopes:

ScopeEndpoints
admin:agents:readGET /v1/admin/agents
admin:agents:writePOST /v1/admin/agents, DELETE /v1/admin/agents/{name}
admin:backends:readGET /v1/admin/backends
admin:backends:writePOST /v1/admin/backends, DELETE /v1/admin/backends/{name}
admin:tokens:readGET /v1/admin/tokens
admin:tokens:writeDELETE /v1/admin/tokens/{id}
admin:audit:readGET /v1/admin/audit
admin:enrollments:readGET /v1/admin/pending
admin:enrollments:writePOST /v1/admin/pending/{id}/*
admin:plugins:writePOST /v1/admin/plugins/*
admin:keys:readGET /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_xxx

Response

{ "access_token": "eyJhbGciOiJSUzI1NiIs...", "token_type": "Bearer", "expires_in": 3600 }

Discovery Document

GET /.well-known/openid-configuration

JWKS

GET /.well-known/jwks.json

Agent Management (Admin)

List Agents

GET /v1/admin/agents

Requires: 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/agents

Requires: admin:agents:write

Request Body

FieldTypeRequiredDescription
namestringYesAgent name
scopesstring[]NoAllowed scopes
expires_instringNoTTL (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/status

Returns 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/active

Response

[ { "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-key

Returns 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/self

This:

  • Revokes all active backend credentials
  • Deletes signing keys
  • Deletes the agent

Returns 204 No Content on success.


Enrollment Endpoints

Initiate Enrollment

POST /v1/enroll

No authentication required.

Request Body

FieldTypeRequiredDescription
namestringYesAgent name
scopesstring[]NoRequested scopes

Response

{ "enrollment_id": "enr_abc123", "status": "pending", "poll_url": "/v1/enroll/enr_abc123/status" }

Poll Enrollment Status

GET /v1/enroll/{id}/status

Response (Pending)

{ "status": "pending" }

Response (Approved)

{ "status": "approved", "token": "ckr_abc123...", "scopes": ["github:read"] }

List Pending Enrollments (Admin)

GET /v1/admin/pending

Requires: admin:enrollments:read

Approve Enrollment (Admin)

POST /v1/admin/pending/{id}/approve

Requires: admin:enrollments:write

Request Body (optional)

FieldTypeDescription
scopesstring[]Override requested scopes

Reject Enrollment (Admin)

POST /v1/admin/pending/{id}/reject

Requires: admin:enrollments:write


Backend Management (Admin)

List Backends

GET /v1/admin/backends

Requires: admin:backends:read

Create Backend

POST /v1/admin/backends

Requires: admin:backends:write

Request Body

FieldTypeRequiredDescription
typestringYesBackend type (github, doppler, etc.)
namestringNoCustom name (defaults to type)
configobjectYesBackend-specific configuration

Delete Backend

DELETE /v1/admin/backends/{name}

Requires: admin:backends:write


Token Management (Admin)

List All Active Tokens

GET /v1/admin/tokens

Requires: admin:tokens:read

Query Parameters

ParameterDescription
backendFilter by backend
agentFilter by agent name

Revoke Token

DELETE /v1/admin/tokens/{id}

Requires: admin:tokens:write


Audit Log (Admin)

GET /v1/admin/audit

Requires: admin:audit:read

Query Parameters

ParameterDescription
limitMax results (default 100)
agent_idFilter by agent ID
actionFilter by action type

Health Check

GET /health

No authentication required.

{ "status": "ok" }

Error Responses

{ "error": "description of what went wrong" }
HTTP StatusMeaning
400Bad request (invalid parameters)
401Missing or invalid authentication
403Insufficient permissions
404Resource not found
500Server error
Last updated on

Apache 2.0 2026 © Creddy