API Reference

Sirr exposes HTTP endpoints for secrets management, audit logging, webhooks, and scoped API keys. All endpoints except /health require a Bearer token — either your SIRR_MASTER_KEY or a scoped API key. Requests and responses use JSON.


POST/secrets

Create a secret

Create an encrypted secret. The value is encrypted at rest using ChaCha20Poly1305 with a per-record nonce derived from your master key via Argon2id.

Required attributes

  • Name
    key
    Type
    string
    Description

    Unique identifier for the secret. Used to retrieve or delete it later.

  • Name
    value
    Type
    string
    Description

    The secret value to encrypt and store.

Optional attributes

  • Name
    ttl_seconds
    Type
    integer
    Description

    Time-to-live in seconds. The secret is automatically destroyed after this duration. Omit for no expiration.

  • Name
    max_reads
    Type
    integer
    Description

    Maximum number of times the secret can be read. The secret is permanently destroyed after this many reads. Omit for unlimited reads.

Request

POST
/secrets
curl -X POST http://localhost:39999/secrets \
  -H "Authorization: Bearer $SIRR_MASTER_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "DB_URL",
    "value": "postgres://user:pass@db:5432/myapp",
    "ttl_seconds": 3600,
    "max_reads": 1
  }'

Response (201)

{
  "key": "DB_URL"
}

Error (402)

{
  "error": "secret limit reached",
  "message": "Free tier allows up to 100 active secrets. Set SIRR_LICENSE_KEY to unlock unlimited usage."
}

GET/secrets

List secrets

List metadata for all active secrets. This endpoint never returns secret values — only keys, timestamps, and read counters. This is a deliberate security design choice.

Request

GET
/secrets
curl http://localhost:39999/secrets \
  -H "Authorization: Bearer $SIRR_MASTER_KEY"

Response

{
  "secrets": [
    {
      "key": "DB_URL",
      "created_at": 1700000000,
      "expires_at": 1700003600,
      "max_reads": 1,
      "read_count": 0
    }
  ]
}

GET/secrets/:key

Retrieve a secret

Retrieve and decrypt a secret by its key. Each call increments the read counter. If the secret has reached its max_reads limit, it is permanently destroyed after this response. Returns 404 if the secret has expired, been burned, or does not exist.

Path parameters

  • Name
    key
    Type
    string
    Description

    The key of the secret to retrieve.

Request

GET
/secrets/:key
curl http://localhost:39999/secrets/DB_URL \
  -H "Authorization: Bearer $SIRR_MASTER_KEY"

Response

{
  "key": "DB_URL",
  "value": "postgres://user:pass@db:5432/myapp"
}

Error (404)

{
  "error": "not found or expired"
}

Error (410) — sealed

{
  "error": "secret is sealed — reads exhausted"
}

DELETE/secrets/:key

Delete a secret

Permanently delete a secret immediately, regardless of its TTL or remaining reads.

Path parameters

  • Name
    key
    Type
    string
    Description

    The key of the secret to delete.

Request

DELETE
/secrets/:key
curl -X DELETE http://localhost:39999/secrets/DB_URL \
  -H "Authorization: Bearer $SIRR_MASTER_KEY"

Response

{
  "deleted": true
}

POST/prune

Prune expired secrets

Delete all expired secrets from the database. This is a housekeeping endpoint that reclaims storage by removing secrets whose TTL has elapsed. Returns the count of pruned secrets.

Request

POST
/prune
curl -X POST http://localhost:39999/prune \
  -H "Authorization: Bearer $SIRR_MASTER_KEY"

Response

{
  "pruned": 3
}

PATCH/secrets/:key

Update a secret

Update the TTL or read limit of an existing secret without changing its value.

Path parameters

  • Name
    key
    Type
    string
    Description

    The key of the secret to update.

Optional attributes

  • Name
    ttl_seconds
    Type
    integer
    Description

    New time-to-live in seconds from now.

  • Name
    max_reads
    Type
    integer
    Description

    New maximum read count.

Request

PATCH
/secrets/:key
curl -X PATCH http://localhost:39999/secrets/DB_URL \
  -H "Authorization: Bearer $SIRR_MASTER_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "ttl_seconds": 7200 }'

Response

{
  "key": "DB_URL",
  "updated": true
}

Audit logs

Query the append-only audit trail of secret operations. See the full Audit Logs documentation for details.

EndpointDescription
GET /auditQuery audit log entries with filters (since, until, action, key, limit)

Webhooks

Register HTTP endpoints to receive real-time event notifications. See the full Webhooks documentation.

EndpointDescription
POST /webhooksRegister a new webhook endpoint
GET /webhooksList all registered webhooks
DELETE /webhooks/:idRemove a webhook

Principal keys

Principals can create named API keys via the /me/keys endpoints. Keys support optional validity windows and are shown only once on creation.

EndpointDescription
POST /me/keysCreate a new principal key
DELETE /me/keys/:idRevoke a principal key

GET/health

Health check

Check whether the Sirr server is running and ready to accept requests. This endpoint does not require authentication and is suitable for load balancer health checks and uptime monitoring.

Request

GET
/health
curl http://localhost:39999/health

Response

{
  "status": "ok"
}

Org-Scoped API (Multi-Tenant)

Sirr supports multi-tenant isolation through organizations, principals, and role-based access control. Org-scoped endpoints live under /orgs/{org_id}/ and require authentication via either the master key (SIRR_API_KEY) or a principal key. Master key holders have full access; principal key holders are limited by their assigned role's permissions.


POST/orgs

Create an org

Create a new organization. Requires master key authentication.

Required attributes

  • Name
    name
    Type
    string
    Description

    Human-readable name for the organization.

Optional attributes

  • Name
    metadata
    Type
    object
    Description

    Arbitrary key-value metadata for the organization.

Request

POST
/orgs
curl -X POST http://localhost:39999/orgs \
  -H "Authorization: Bearer $SIRR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "acme-corp" }'

Response (201)

{
  "id": "org_a1b2c3d4",
  "name": "acme-corp",
  "created_at": 1700000000
}

GET/orgs

List orgs

List all organizations. Requires master key authentication.

Request

GET
/orgs
curl http://localhost:39999/orgs \
  -H "Authorization: Bearer $SIRR_API_KEY"

Response

{
  "orgs": [
    {
      "id": "org_a1b2c3d4",
      "name": "acme-corp",
      "created_at": 1700000000
    }
  ]
}

DELETE/orgs/:org_id

Delete an org

Delete an organization. The org must have no principals — cascading deletes are not allowed. Requires master key authentication.

Path parameters

  • Name
    org_id
    Type
    string
    Description

    The ID of the organization to delete.

Request

DELETE
/orgs/:org_id
curl -X DELETE http://localhost:39999/orgs/org_a1b2c3d4 \
  -H "Authorization: Bearer $SIRR_API_KEY"

Response

{
  "deleted": true
}

POST/orgs/:org_id/principals

Create a principal

Create a new principal (user or service account) within an organization. Requires master key authentication.

Path parameters

  • Name
    org_id
    Type
    string
    Description

    The organization to create the principal in.

Required attributes

  • Name
    name
    Type
    string
    Description

    Human-readable name for the principal.

  • Name
    role
    Type
    string
    Description

    The role to assign. Built-in roles: reader, writer, admin, owner. Custom roles can be created per-org.

Request

POST
/orgs/:org_id/principals
curl -X POST http://localhost:39999/orgs/org_a1b2c3d4/principals \
  -H "Authorization: Bearer $SIRR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "ci-bot", "role": "writer" }'

Response (201)

{
  "id": "prin_e5f6a7b8",
  "name": "ci-bot",
  "org_id": "org_a1b2c3d4",
  "role": "writer",
  "created_at": 1700000000
}

GET/orgs/:org_id/principals

List principals

List all principals in an organization. Requires master key authentication.

Path parameters

  • Name
    org_id
    Type
    string
    Description

    The organization to list principals for.

Request

GET
/orgs/:org_id/principals
curl http://localhost:39999/orgs/org_a1b2c3d4/principals \
  -H "Authorization: Bearer $SIRR_API_KEY"

Response

{
  "principals": [
    {
      "id": "prin_e5f6a7b8",
      "name": "ci-bot",
      "org_id": "org_a1b2c3d4",
      "role": "writer",
      "created_at": 1700000000
    }
  ]
}

DELETE/orgs/:org_id/principals/:id

Delete a principal

Delete a principal. The principal must have no active keys — cascading deletes are not allowed. Requires master key authentication.

Path parameters

  • Name
    org_id
    Type
    string
    Description

    The organization the principal belongs to.

  • Name
    id
    Type
    string
    Description

    The ID of the principal to delete.

Request

DELETE
/orgs/:org_id/principals/:id
curl -X DELETE http://localhost:39999/orgs/org_a1b2c3d4/principals/prin_e5f6a7b8 \
  -H "Authorization: Bearer $SIRR_API_KEY"

Response

{
  "deleted": true
}

POST/orgs/:org_id/roles

Create a role

Create a custom role for an organization. Requires master key authentication.

Built-in roles (reader, writer, admin, owner) are always available and cannot be modified. Custom roles let you define fine-grained permission sets.

Path parameters

  • Name
    org_id
    Type
    string
    Description

    The organization to create the role in.

Required attributes

  • Name
    name
    Type
    string
    Description

    Unique name for the role within this org.

  • Name
    permissions
    Type
    string
    Description

    Permission letter string. Each letter enables a permission bit. Example: "rRlL" grants secret read, secret list, audit read, and audit list.

Request

POST
/orgs/:org_id/roles
curl -X POST http://localhost:39999/orgs/org_a1b2c3d4/roles \
  -H "Authorization: Bearer $SIRR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "auditor", "permissions": "rRlL" }'

Response (201)

{
  "name": "auditor",
  "org_id": "org_a1b2c3d4",
  "permissions": "rRlL"
}

GET/orgs/:org_id/roles

List roles

List all roles (built-in and custom) for an organization. Requires master key authentication.

Path parameters

  • Name
    org_id
    Type
    string
    Description

    The organization to list roles for.

Request

GET
/orgs/:org_id/roles
curl http://localhost:39999/orgs/org_a1b2c3d4/roles \
  -H "Authorization: Bearer $SIRR_API_KEY"

Response

{
  "roles": [
    { "name": "reader", "permissions": "rRl", "builtin": true },
    { "name": "writer", "permissions": "rRlLcCpP", "builtin": true },
    { "name": "admin", "permissions": "rRlLcCpPaAmM", "builtin": true },
    { "name": "owner", "permissions": "rRlLcCpPaAmMdD", "builtin": true },
    { "name": "auditor", "permissions": "rRlL", "builtin": false }
  ]
}

DELETE/orgs/:org_id/roles/:name

Delete a role

Delete a custom role. Built-in roles cannot be deleted. Requires master key authentication.

Path parameters

  • Name
    org_id
    Type
    string
    Description

    The organization the role belongs to.

  • Name
    name
    Type
    string
    Description

    The name of the custom role to delete.

Request

DELETE
/orgs/:org_id/roles/:name
curl -X DELETE http://localhost:39999/orgs/org_a1b2c3d4/roles/auditor \
  -H "Authorization: Bearer $SIRR_API_KEY"

Response

{
  "deleted": true
}

GET/me

Get current identity

Returns the authenticated principal's identity, org, role, and permissions. Works with any principal key.

Request

GET
/me
curl http://localhost:39999/me \
  -H "Authorization: Bearer $SIRR_PRINCIPAL_KEY"

Response

{
  "id": "p_e5f6a7b8",
  "name": "deploy-bot",
  "role": "writer",
  "org_id": "org_a1b2c3d4",
  "metadata": {},
  "created_at": 1700000000,
  "keys": [
    {
      "id": "k_c9d0e1f2",
      "name": "ci-deploy",
      "valid_after": 1700000000,
      "valid_before": 1732000000,
      "created_at": 1700000000
    }
  ]
}

PATCH/me

Update current identity

Update the authenticated principal's metadata. Works with any principal key.

Optional attributes

  • Name
    metadata
    Type
    object
    Description

    Arbitrary key-value metadata to set on the principal.

Request

PATCH
/me
curl -X PATCH http://localhost:39999/me \
  -H "Authorization: Bearer $SIRR_PRINCIPAL_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "metadata": { "team": "platform" } }'

Response

{
  "id": "p_e5f6a7b8",
  "name": "deploy-bot",
  "role": "writer",
  "org_id": "org_a1b2c3d4",
  "metadata": { "team": "platform" },
  "created_at": 1700000000,
  "keys": []
}

POST/me/keys

Create a principal key

Create a new API key for the authenticated principal. Each principal can have unlimited named keys with optional time windows.

Required attributes

  • Name
    name
    Type
    string
    Description

    Human-readable label for the key.

Optional attributes

  • Name
    valid_after
    Type
    integer
    Description

    Unix timestamp after which the key becomes valid. Omit for immediate validity.

  • Name
    valid_before
    Type
    integer
    Description

    Unix timestamp after which the key expires. Omit for no expiration.

Request

POST
/me/keys
curl -X POST http://localhost:39999/me/keys \
  -H "Authorization: Bearer $SIRR_PRINCIPAL_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "deploy-key",
    "valid_before": 1700100000
  }'

Response (201)

{
  "id": "k_f3a4b5c6",
  "name": "deploy-key",
  "key": "sirr_key_7f3a9b2c...",
  "valid_after": 1700000000,
  "valid_before": 1700100000
}

DELETE/me/keys/:key_id

Delete a principal key

Permanently revoke one of the authenticated principal's keys. This is a hard delete — the key is immediately unusable.

Path parameters

  • Name
    key_id
    Type
    string
    Description

    The ID of the key to delete.

Request

DELETE
/me/keys/:key_id
curl -X DELETE http://localhost:39999/me/keys/key_f3a4b5c6 \
  -H "Authorization: Bearer $SIRR_PRINCIPAL_KEY"

Response

{
  "deleted": true
}

POST/orgs/:org_id/secrets

Create an org secret

Create a secret within an organization scope. Requires the SecretCreate permission (c).

Path parameters

  • Name
    org_id
    Type
    string
    Description

    The organization to store the secret in.

Required attributes

  • Name
    key
    Type
    string
    Description

    Unique identifier for the secret within this org.

  • Name
    value
    Type
    string
    Description

    The secret value to encrypt and store.

Optional attributes

  • Name
    ttl_seconds
    Type
    integer
    Description

    Time-to-live in seconds. The secret is automatically destroyed after this duration.

  • Name
    max_reads
    Type
    integer
    Description

    Maximum number of reads before the secret is burned.

  • Name
    delete
    Type
    boolean
    Description

    Whether to burn (true, default) or seal (false) on max_reads. Sealed secrets block reads but allow PATCH.

  • Name
    allowed_keys
    Type
    array
    Description

    List of principal key IDs allowed to read this secret. Omit for org-wide access.

Request

POST
/orgs/:org_id/secrets
curl -X POST http://localhost:39999/orgs/org_a1b2c3d4/secrets \
  -H "Authorization: Bearer $SIRR_PRINCIPAL_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "DB_URL",
    "value": "postgres://user:pass@db:5432/myapp",
    "ttl_seconds": 3600,
    "max_reads": 5
  }'

Response (201)

{
  "key": "DB_URL"
}

GET/orgs/:org_id/secrets

List org secrets

List metadata for all active secrets in an organization. Requires the SecretList permission (l). Secret values are never included.

Path parameters

  • Name
    org_id
    Type
    string
    Description

    The organization to list secrets for.

Request

GET
/orgs/:org_id/secrets
curl http://localhost:39999/orgs/org_a1b2c3d4/secrets \
  -H "Authorization: Bearer $SIRR_PRINCIPAL_KEY"

Response

{
  "secrets": [
    {
      "key": "DB_URL",
      "created_at": 1700000000,
      "expires_at": 1700003600,
      "max_reads": 5,
      "read_count": 0,
      "owner_id": "prin_e5f6a7b8"
    }
  ]
}

GET/orgs/:org_id/secrets/:key

Retrieve an org secret

Retrieve and decrypt a secret by key within an organization. Requires the SecretRead permission (r). Each call increments the read counter. Returns 410 Gone if the secret is sealed, 404 if not found.

Path parameters

  • Name
    org_id
    Type
    string
    Description

    The organization the secret belongs to.

  • Name
    key
    Type
    string
    Description

    The key of the secret to retrieve.

Request

GET
/orgs/:org_id/secrets/:key
curl http://localhost:39999/orgs/org_a1b2c3d4/secrets/DB_URL \
  -H "Authorization: Bearer $SIRR_PRINCIPAL_KEY"

Response (200)

{
  "key": "DB_URL",
  "value": "postgres://user:pass@db:5432/myapp"
}

Sealed (410)

{
  "error": "sealed",
  "message": "Secret has been sealed and is no longer readable."
}

HEAD/orgs/:org_id/secrets/:key

Check org secret existence

Check whether a secret exists without reading or decrypting it. Does not increment the read counter. Requires the SecretRead permission (r). Returns 200 if the secret exists, 404 otherwise.

Path parameters

  • Name
    org_id
    Type
    string
    Description

    The organization the secret belongs to.

  • Name
    key
    Type
    string
    Description

    The key to check.

Request

HEAD
/orgs/:org_id/secrets/:key
curl -I http://localhost:39999/orgs/org_a1b2c3d4/secrets/DB_URL \
  -H "Authorization: Bearer $SIRR_PRINCIPAL_KEY"

Response (200)

HTTP/1.1 200 OK

PATCH/orgs/:org_id/secrets/:key

Update an org secret

Update the TTL or read limit of an existing org secret. Only works on secrets created with delete=false (sealable secrets). Requires the SecretPatch permission (P).

Path parameters

  • Name
    org_id
    Type
    string
    Description

    The organization the secret belongs to.

  • Name
    key
    Type
    string
    Description

    The key of the secret to update.

Optional attributes

  • Name
    ttl_seconds
    Type
    integer
    Description

    New time-to-live in seconds from now.

  • Name
    max_reads
    Type
    integer
    Description

    New maximum read count.

Request

PATCH
/orgs/:org_id/secrets/:key
curl -X PATCH http://localhost:39999/orgs/org_a1b2c3d4/secrets/DB_URL \
  -H "Authorization: Bearer $SIRR_PRINCIPAL_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "ttl_seconds": 7200 }'

Response

{
  "key": "DB_URL",
  "updated": true
}

DELETE/orgs/:org_id/secrets/:key

Delete an org secret

Permanently delete a secret from an organization. Requires the SecretDelete permission (d).

Path parameters

  • Name
    org_id
    Type
    string
    Description

    The organization the secret belongs to.

  • Name
    key
    Type
    string
    Description

    The key of the secret to delete.

Request

DELETE
/orgs/:org_id/secrets/:key
curl -X DELETE http://localhost:39999/orgs/org_a1b2c3d4/secrets/DB_URL \
  -H "Authorization: Bearer $SIRR_PRINCIPAL_KEY"

Response

{
  "deleted": true
}

POST/orgs/:org_id/prune

Prune org secrets

Delete all expired secrets within an organization. Requires the SecretPrune permission (C).

Path parameters

  • Name
    org_id
    Type
    string
    Description

    The organization to prune secrets for.

Request

POST
/orgs/:org_id/prune
curl -X POST http://localhost:39999/orgs/org_a1b2c3d4/prune \
  -H "Authorization: Bearer $SIRR_PRINCIPAL_KEY"

Response

{
  "pruned": 7
}

GET/orgs/:org_id/audit

Org audit logs

Query the audit log for an organization. Requires the AuditRead permission (a).

Path parameters

  • Name
    org_id
    Type
    string
    Description

    The organization to query audit logs for.

Query parameters

  • Name
    since
    Type
    integer
    Description

    Only return events after this Unix timestamp.

  • Name
    until
    Type
    integer
    Description

    Only return events before this Unix timestamp.

  • Name
    action
    Type
    string
    Description

    Filter by action type (e.g. secret.read, secret.created).

  • Name
    key
    Type
    string
    Description

    Filter by secret key.

  • Name
    limit
    Type
    integer
    Description

    Maximum number of entries to return.

Request

GET
/orgs/:org_id/audit
curl "http://localhost:39999/orgs/org_a1b2c3d4/audit?limit=20" \
  -H "Authorization: Bearer $SIRR_PRINCIPAL_KEY"

Response

{
  "entries": [
    {
      "timestamp": 1700000100,
      "action": "secret.read",
      "key": "DB_URL",
      "principal_id": "prin_e5f6a7b8",
      "ip": "10.0.0.5"
    }
  ]
}

Org webhooks

Manage webhooks scoped to an organization. Requires the WebhookManage permission (M).

EndpointDescription
POST /orgs/:org_id/webhooksRegister a webhook for org events
GET /orgs/:org_id/webhooksList all webhooks for the org
DELETE /orgs/:org_id/webhooks/:idRemove an org webhook

Was this page helpful?