Workflow Secrets API
Manage write-only secrets scoped to one workflow
Workflow Secrets API
Workflow secrets store encrypted values that belong to a single workflow. Step
config can reference them as {{ secrets.KEY }}. The API never returns
plaintext or ciphertext; reads return only a masked value.
All endpoints require authentication with x-api-key or a Studio session. API
keys need secrets:read for listing and secrets:write for create, rotate, and
delete.
List Secrets
GET /api/v1/workflows/:workflowId/secretsPath Parameters
| Parameter | Type | Description |
|---|---|---|
workflowId | string | Workflow UUID. The workflow must belong to the caller's company. |
Response
{
"success": true,
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"workflowId": "660e8400-e29b-41d4-a716-446655440001",
"key": "SIGNING_KEY",
"maskedValue": "••••1234",
"lastUsedAt": null,
"createdAt": "2026-06-26T10:00:00.000Z",
"updatedAt": "2026-06-26T10:00:00.000Z"
}
]
}maskedValue is built from a stored suffix hint when the value is long enough to
keep at least one character hidden; shorter values return only the mask prefix.
The read path does not decrypt the value.
Example
curl -X GET "http://localhost:3000/api/v1/workflows/WORKFLOW_ID/secrets" \
-H "x-api-key: YOUR_API_KEY"Create Secret
POST /api/v1/workflows/:workflowId/secretsRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
key | string | Yes | Upper snake case, starts with a letter, max 64 characters. Example: SIGNING_KEY. |
value | string | Yes | Secret value, 1-8192 characters. Returned only through this write request's side effect, never in the response. |
Example Request
{
"key": "SIGNING_KEY",
"value": "YOUR_SECRET_VALUE"
}Response
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"workflowId": "660e8400-e29b-41d4-a716-446655440001",
"key": "SIGNING_KEY",
"maskedValue": "••••ALUE",
"lastUsedAt": null,
"createdAt": "2026-06-26T10:00:00.000Z",
"updatedAt": "2026-06-26T10:00:00.000Z"
}
}Creating the same key twice for one workflow returns 409 CONFLICT.
Rotate Secret
PUT /api/v1/workflows/:workflowId/secrets/:keyRotation is write-without-read: submit the replacement value and the API stores a new encrypted value without revealing the previous one.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
value | string | Yes | Replacement value, 1-8192 characters. |
Example
curl -X PUT "http://localhost:3000/api/v1/workflows/WORKFLOW_ID/secrets/SIGNING_KEY" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"value":"NEW_SECRET_VALUE"}'Delete Secret
DELETE /api/v1/workflows/:workflowId/secrets/:keyResponse
{
"success": true,
"data": {
"deleted": true
}
}Deleting a secret does not rewrite workflow step config. Future runs that still
reference {{ secrets.KEY }} fail fast with a missing-secret error until the key
is recreated or the workflow is updated.
Errors
| Status | Code | When |
|---|---|---|
400 | VALIDATION_ERROR | Invalid key format or empty value. |
401 | UNAUTHORIZED | Missing or invalid authentication. |
403 | FORBIDDEN | Authenticated caller lacks the required secrets:* scope. |
404 | NOT_FOUND | Workflow is not owned by the caller's company, or the secret key does not exist. |
409 | CONFLICT | Secret key already exists for this workflow. |
Loopfour