Create Approval Request
POST /api/v1/approvals/request -- submit an action for human approval and receive a request ID to track the decision.
Key Concepts
The create request endpoint is the entry point for the approval flow. Your application describes the action that needs human approval, specifies a time-to-live, and optionally includes metadata and a callback URL. The response includes a request ID that you use to poll for the decision.
Endpoint
POST https://signedapproval.net/api/v1/approvals/request
Authorization: Bearer sa_live_...
Content-Type: application/jsonRequest Body
{
"action": "Deploy v2.1.0 to production",
"ttl_seconds": 3600,
"metadata": {
"environment": "production",
"version": "2.1.0",
"commit": "abc123"
},
"callback_url": "https://your-app.com/webhook/approval"
}Field descriptions:
- action (required, string) -- Human-readable description of the action needing approval. This is shown to the approver in the dashboard and push notification. Maximum 500 characters.
- ttl_seconds (optional, integer) -- How long the request stays pending before expiring. If omitted, the approver's default TTL is used. Must be between 60 and 604800 (1 minute to 7 days).
- metadata (optional, object) -- Arbitrary key-value data attached to the request. Shown to the approver for context. Maximum 4 KB when serialized.
- callback_url (optional, string) -- URL to POST the decision to when the approver decides. Must be HTTPS in production. The callback is HMAC-signed with your per-API-key signing secret; retrieve it from
GET /api/v1/account/webhook-secret.
Response
Success (201 Created):
{
"id": "req_abc123def456",
"status": "pending",
"action": "Deploy v2.1.0 to production",
"metadata": {
"environment": "production",
"version": "2.1.0",
"commit": "abc123"
},
"created_at": "2026-03-23T14:00:00.000Z",
"expires_at": "2026-03-23T15:00:00.000Z"
}Error responses:
// 400 Bad Request -- missing required fields
{ "error": "action is required" }
// 401 Unauthorized -- invalid or missing API key
{ "error": "Invalid API key" }
// 429 Too Many Requests -- rate limited
{ "error": "Rate limit exceeded", "retry_after": 30 }Examples
Minimal request:
curl -X POST https://signedapproval.net/api/v1/approvals/request \
-H "Authorization: Bearer sa_live_abc123..." \
-H "Content-Type: application/json" \
-d '{"action": "Run database migration"}'Full request with all options:
curl -X POST https://signedapproval.net/api/v1/approvals/request \
-H "Authorization: Bearer sa_live_abc123..." \
-H "Content-Type: application/json" \
-d '{
"action": "Transfer $2,500 to vendor Acme Corp",
"ttl_seconds": 300,
"metadata": {
"amount": 2500,
"currency": "USD",
"vendor": "Acme Corp",
"invoice": "INV-2026-0042"
},
"callback_url": "https://api.example.com/webhooks/approval"
}'Using internal service token with approver routing:
curl -X POST https://signedapproval.net/api/v1/approvals/request \
-H "Authorization: Bearer internal-your_service_token" \
-H "X-Approver-Email: approver@example.com" \
-H "Content-Type: application/json" \
-d '{"action": "CleverAgent: Navigate to bank portal and initiate wire", "ttl_seconds": 300}'Note
The
action text is hashed (SHA-256, first 16 chars) and included in the signed payload. Choose descriptive action text -- it helps the approver make an informed decision and creates a clear audit trail.Tip
Use the
metadata field to pass structured context that helps the approver. For example, include the commit SHA, environment name, dollar amount, or any other relevant details. Metadata is shown in the dashboard alongside the action text.Related Articles