Execute
Provider-shaped execution for governed Keel requests.
Use POST /v1/execute when you want Keel to run a governed execution from a provider-shaped input payload instead of the stricter canonical /v1/executions request shape.
This route still returns the normalized execution envelope, but it resolves the concrete provider and model target first and includes a resolved block in the response.
Need to choose between execution surfaces first? See the route comparison in Quickstart.
Route summary
| Route | Status | Purpose |
|---|---|---|
POST /v1/execute | Official public | Execute a governed request from a provider-shaped input object and return the normalized execution envelope plus resolved-target metadata. |
Authentication and idempotency
Authorization: Bearer <client_project_api_key>
Idempotency-Key: exec-001/v1/execute requires a client-scoped project API key.
Execution routes infer project context from the project API key and do not require
project_idin the request body.
If Idempotency-Key is omitted, the request is treated as a new execution.
Proxy routes still have the strongest public same-key replay contract. Treat /v1/execute idempotency as route-specific and do not assume it inherits every proxy replay guarantee.
On hosted Keel runtimes, execution routes may require additional request freshness headers. Keel rejects requests that fail freshness validation.
Request shape
{
"provider": "openai",
"model": "gpt-4o-mini",
"input": {
"messages": [
{"role": "user", "content": "Summarize this request in one sentence."}
],
"max_tokens": 80
}
}| Field | Required? | Notes |
|---|---|---|
provider | No | If omitted, Keel resolves the provider from project configuration. |
model | Yes | Requested model id or alias. |
input | Yes | Provider-shaped request payload. Operation and modality are inferred from this payload after provider resolution. |
POST /v1/execute does not expose a public top-level context field.
Provider and model resolution
If provider is supplied, Keel uses it directly. If omitted, Keel resolves the target from project configuration. If the target cannot be determined unambiguously, the request fails.
This route does not expose the same public cross-provider fallback contract as POST /v1/executions.
What Keel does on this route
POST /v1/execute applies the same governance model as other execution routes: the caller is authenticated, governance runs before provider dispatch, execution uses Keel-managed provider credentials, and usage and audit data are recorded.
Response shape
POST /v1/execute returns the same normalized execution envelope shape used by POST /v1/executions, plus a resolved block.
At minimum, the documented resolved contract includes:
provider: always present in the documented examples and identifies the final provider Keel targeted.model: always present in the documented examples and identifies the final resolved model id Keel targeted.
Additional metadata fields may appear in resolved when relevant. Treat any fields beyond provider and model as optional.
Denied and failed results still use this normalized execution envelope. A standalone top-level { "error": ... } object is reserved for request-level API failures before Keel can return an execution object.
The HTTP response may also include Keel-specific headers with additional metadata about the execution.
If you need the associated permit id for correlation, read the x-keel-permit-id response header. The body’s governance block is decision-focused.
API example
curl
curl -i -sS https://api.keelapi.com/v1/execute \
-H "Authorization: Bearer keel_sk_your_key_here" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: exec-001" \
-d '{
"provider": "openai",
"model": "gpt-4o-mini",
"input": {
"messages": [
{"role": "user", "content": "Summarize governed execution in one sentence."}
],
"max_tokens": 80
}
}'Test this request in the Playground: Try in PlaygroundÂ
JavaScript
const response = await fetch('https://api.keelapi.com/v1/execute', {
method: 'POST',
headers: {
Authorization: 'Bearer keel_sk_your_key_here',
'Content-Type': 'application/json',
'Idempotency-Key': 'exec-001'
},
body: JSON.stringify({
provider: 'openai',
model: 'gpt-4o-mini',
input: {
messages: [
{
role: 'user',
content: 'Summarize governed execution in one sentence.'
}
],
max_tokens: 80
}
})
})
const data = await response.json()
console.log(data)Python
import requests
response = requests.post(
"https://api.keelapi.com/v1/execute",
headers={
"Authorization": "Bearer keel_sk_your_key_here",
"Content-Type": "application/json",
"Idempotency-Key": "exec-001",
},
json={
"provider": "openai",
"model": "gpt-4o-mini",
"input": {
"messages": [
{
"role": "user",
"content": "Summarize governed execution in one sentence.",
}
],
"max_tokens": 80,
},
},
)
print(response.json())Response example
{
"id": "exec_req_01hy0m9m1d3z5r8j52x6m7n8pq",
"object": "execution",
"created_at": "2026-03-11T00:00:00Z",
"status": "completed",
"status_code": 200,
"output": {
"content": [
{
"type": "text",
"role": "assistant",
"text": "Keel resolved the target, enforced governance, executed the request, and recorded usage."
}
]
},
"output_assets": [],
"routing": {
"requested_provider": "openai",
"requested_model": "gpt-4o-mini",
"selected_provider": "openai",
"selected_model": "gpt-4o-mini",
"reason_code": "explicit_request",
"fallback_occurred": false
},
"governance": {
"decision": "allow",
"reason": "ok",
"actions": [],
"constraints": null,
"budgets": null
},
"usage": {
"input_tokens": 27,
"output_tokens": 14,
"total_tokens": 41,
"cost_usd_micros": 13,
"estimated_final": false
},
"timing": {
"started_at": "2026-03-11T00:00:00Z",
"completed_at": "2026-03-11T00:00:01Z",
"duration_ms": 811
},
"error": null,
"resolved": {
"provider": "openai",
"model": "gpt-4o-mini",
"alias": null
}
}const requestId = data.id
const status = data.status
const text =
data.output?.content?.find(block => block.type === 'text')?.text ?? null
const routingReason = data.routing?.reason_code ?? null
const permitId = response.headers.get('x-keel-permit-id')
const errorCode = data.error?.code ?? null
const errorMessage = data.error?.message ?? nullError response examples
Denied
{
"id": "exec_req_01hy0m9m1d3z5r8j52x6m7n8pr",
"object": "execution",
"created_at": "2026-03-11T00:00:00Z",
"status": "denied",
"status_code": 403,
"output": null,
"output_assets": [],
"routing": {
"requested_provider": "openai",
"requested_model": "gpt-4o-mini",
"selected_provider": "openai",
"selected_model": "gpt-4o-mini",
"reason_code": "explicit_request",
"fallback_occurred": false
},
"governance": {
"decision": "deny",
"reason": "...",
"actions": [
{
"type": "deny",
"message": "The request did not satisfy the configured project policy."
}
],
"constraints": null,
"budgets": null
},
"usage": {
"input_tokens": 0,
"output_tokens": 0,
"total_tokens": 0,
"cost_usd_micros": 0,
"estimated_final": false
},
"timing": {
"started_at": "2026-03-11T00:00:00Z",
"completed_at": "2026-03-11T00:00:00Z",
"duration_ms": 17
},
"error": {
"code": "denied",
"message": "The request did not satisfy the configured project policy."
},
"resolved": {
"provider": "openai",
"model": "gpt-4o-mini"
}
}const requestId = denied.id
const status = denied.status
const text = denied.output?.content?.find(block => block.type === 'text')?.text ?? null
const permitId = response.headers.get('x-keel-permit-id')
const errorCode = denied.error?.code ?? null
const errorMessage = denied.error?.message ?? nullFailed
{
"id": "exec_req_01hy0m9m1d3z5r8j52x6m7n8ps",
"object": "execution",
"created_at": "2026-03-11T00:00:00Z",
"status": "failed",
"status_code": 502,
"output": null,
"output_assets": [],
"routing": {
"requested_provider": "openai",
"requested_model": "gpt-4o-mini",
"selected_provider": "openai",
"selected_model": "gpt-4o-mini",
"reason_code": "explicit_request",
"fallback_occurred": false
},
"governance": {
"decision": "allow",
"reason": "ok",
"actions": [],
"constraints": null,
"budgets": null
},
"usage": {
"input_tokens": 27,
"output_tokens": 0,
"total_tokens": 27,
"cost_usd_micros": 9,
"estimated_final": false
},
"timing": {
"started_at": "2026-03-11T00:00:00Z",
"completed_at": "2026-03-11T00:00:01Z",
"duration_ms": 544
},
"error": {
"code": "upstream_error",
"message": "The upstream provider request failed."
},
"resolved": {
"provider": "openai",
"model": "gpt-4o-mini"
}
}const requestId = failed.id
const status = failed.status
const text = failed.output?.content?.find(block => block.type === 'text')?.text ?? null
const permitId = response.headers.get('x-keel-permit-id')
const errorCode = failed.error?.code ?? null
const errorMessage = failed.error?.message ?? nullProvider-shaped execution vs provider-neutral execution
| Concern | /v1/execute | /v1/executions |
|---|---|---|
| Request shape | Provider-shaped input object | Canonical operation plus messages or inputs |
| Provider selection | Optional explicit provider, otherwise resolved from alias or registry | Canonical routing block |
| Operation selection | Inferred from resolved provider payload | Explicit operation |
| Response shape | Normalized envelope plus resolved | Normalized envelope |
| Best fit | Lower-level integrations that already have provider-shaped payloads | Portable integrations that want the canonical request contract |
For the full route matrix, see Route comparison.
Current limits
- sync only
- provider-native payload semantics still vary by provider
- this route does not expose the same public cross-provider fallback interface as
/v1/executions - Prompt Firewall coverage depends on the execution route and payload format