Skip to content

API Keys Reference

CRUD operations for managing operator API keys.

Base path: /functions/v1/api-keys

Authentication: Authorization: Bearer oh_live_... or Supabase JWT (for listing and management)


Create a key {#create}

POST /api-keys

Creates a new API key for an operator. The plaintext key is returned once in the response — store it securely.

Request

FieldTypeRequiredDescription
operatorIdstringYesThe operator ID to create the key for
labelstringNoA descriptive label (e.g. "Production backend")

Example

bash
curl -X POST https://api.onehazel.com/api-keys \
  -H "Content-Type: application/json" \
  -d '{
    "operatorId": "op_abc123",
    "label": "Production backend"
  }'

Response (201)

json
{
  "success": true,
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "key": "oh_live_a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456",
    "label": "Production backend",
    "createdAt": "2026-04-06T12:00:00.000Z"
  }
}

Store your key

The key field is only returned in this response. It is stored as a SHA-256 hash and cannot be retrieved later. If you lose it, revoke the key and create a new one.


List keys {#list}

GET /api-keys

Lists all API keys for the authenticated operator. Keys are returned with hashed values — never in plaintext.

Supports both API key auth (oh_live_...) and JWT auth (Supabase session). When authenticated, results are filtered to show only the operator's own keys.

Example

bash
curl https://api.onehazel.com/api-keys \
  -H "Authorization: Bearer oh_live_YOUR_API_KEY"

Response

json
{
  "success": true,
  "data": [
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "operatorId": "op_abc123",
      "keyHash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
      "label": "Production backend",
      "createdAt": "2026-04-06T12:00:00.000Z",
      "lastUsedAt": "2026-04-06T14:30:00.000Z",
      "revoked": false
    },
    {
      "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
      "operatorId": "op_abc123",
      "keyHash": "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592",
      "label": "Staging ETL",
      "createdAt": "2026-03-15T09:00:00.000Z",
      "lastUsedAt": null,
      "revoked": false
    }
  ]
}

Rename a key {#rename}

PATCH /api-keys

Updates the label on an existing key.

Request

FieldTypeRequiredDescription
idstringYesThe key ID
labelstringYesThe new label

Example

bash
curl -X PATCH https://api.onehazel.com/api-keys \
  -H "Authorization: Bearer oh_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "label": "Production v2"
  }'

Response

json
{
  "success": true,
  "message": "Key renamed"
}

Revoke a key {#revoke}

DELETE /api-keys?id=<keyId>

Soft-revokes an API key. The key remains in the database but can no longer be used for authentication.

Query parameters

ParameterTypeRequiredDescription
idstringYesThe key ID to revoke

Example

bash
curl -X DELETE "https://api.onehazel.com/api-keys?id=a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
  -H "Authorization: Bearer oh_live_YOUR_API_KEY"

Response

json
{
  "success": true,
  "message": "Key revoked"
}

Last-key guard

You cannot revoke your last active API key. If you try, the API returns:

json
{
  "success": false,
  "error": "Cannot revoke your last active API key — create a new one first"
}

HTTP status: 400


Hard delete a key {#hard-delete}

DELETE /api-keys?id=<keyId>&hard=true

Permanently removes a revoked key from the database.

Prerequisite: The key must already be revoked. Attempting to hard-delete an active key returns an error.

Example

bash
curl -X DELETE "https://api.onehazel.com/api-keys?id=a1b2c3d4-e5f6-7890-abcd-ef1234567890&hard=true" \
  -H "Authorization: Bearer oh_live_YOUR_API_KEY"

Response

json
{
  "success": true,
  "message": "Key deleted"
}

Error for active key

json
{
  "success": false,
  "error": "Cannot delete an active key — revoke it first"
}

Error codes

HTTP StatusErrorDescription
400operatorId is requiredMissing operatorId on create
400id and label are requiredMissing fields on rename
400Query parameter 'id' is requiredMissing key ID on delete
400Cannot revoke your last active API keyLast-key guard
400Cannot delete an active keyMust revoke before hard delete
405Method not allowedUnsupported HTTP method
500Failed to create keyDatabase error on create
500Failed to list keysDatabase error on list
500Failed to rename keyDatabase error on rename
500Failed to revoke keyDatabase error on revoke
500Failed to delete keyDatabase error on delete