niyra_execute
The "do this for me" tool. Unlike niyra_ask, niyra_execute is allowed to invoke Niyra's full tool registry — email, calendar, web search, integrations, code execution, you name it.
When to use
- "Email Sarah and ask if next Tuesday at 3pm works for the kickoff."
- "Pull the Linear tickets tagged P0 and summarize them."
- "Research recent funding rounds in Series B vertical SaaS and draft a brief."
If the request is just "what is X" — that's niyra_ask.
Endpoint
| Method | Path | Auth | Scope |
|---|---|---|---|
| POST | /v1/public/execute | Bearer token (PAT or OAuth) | niyra:execute |
MCP equivalent: POST /mcp with method tools/call, name niyra_execute.
Request
{
"instruction": "Email sarah@acme.com and propose Tuesday 3pm for the kickoff.",
"conversation_id": "optional-uuid",
"approval_mode": "auto",
"channel_context": "from my CI pipeline"
}
| Field | Type | Required | Notes |
|---|---|---|---|
instruction | string | yes | What you want Niyra to do. Max 8000 chars. |
conversation_id | uuid | no | Pin to a thread for context continuity. |
approval_mode | enum | no | auto (default — Niyra decides), dry_run (plan only, no side effects), confirm (return a plan; second call with confirmed_task_id to execute) |
channel_context | string | no | Where this request came from — colors Niyra's tone. |
Response — synchronous case
Returned when the work finishes inside the 60-second window:
{
"result": "Sent. Sarah replied that Tuesday works — confirmed for 3pm.",
"conversation_id": "8f3b…",
"task_id": "task_xyz",
"tools_used": ["gmail_send", "gmail_read"],
"elapsed_ms": 8420,
"terminal": true
}
Response — spawn-on-timeout case
When the work crosses 60 seconds, the same request returns:
{
"result": null,
"conversation_id": "8f3b…",
"task_id": "task_xyz",
"status": "running",
"elapsed_ms": 60000,
"terminal": false
}
Poll GET /v1/public/tasks/{task_id} until terminal: true. The task keeps running on Niyra's side regardless of whether you poll — losing the connection doesn't lose the work.
Code examples
curl
curl -X POST https://api.niyra.ai/v1/public/execute \
-H "Authorization: Bearer pat_…" \
-H "Content-Type: application/json" \
-d '{
"instruction": "Summarize the Linear tickets tagged P0 this week."
}'
JavaScript with polling
async function niyraExecute(instruction, token) {
const start = await fetch("https://api.niyra.ai/v1/public/execute", {
method: "POST",
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
body: JSON.stringify({ instruction }),
}).then((r) => r.json());
if (start.terminal) return start.result;
// Poll every 3s, give up after 10 minutes.
for (let i = 0; i < 200; i++) {
await new Promise((r) => setTimeout(r, 3000));
const tick = await fetch(
`https://api.niyra.ai/v1/public/tasks/${start.task_id}`,
{ headers: { Authorization: `Bearer ${token}` } }
).then((r) => r.json());
if (tick.terminal) return tick.result;
}
throw new Error("Task did not terminate within 10 minutes");
}
Approval modes
| Mode | What happens |
|---|---|
auto | Niyra plans and executes in one shot. Default. |
dry_run | Returns the plan Niyra would execute, with no side effects. Useful for previewing before committing. |
confirm | Returns a plan with a pending_task_id. Send a second execute call with confirmed_task_id: <id> to run it. |
Errors
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_request | Empty instruction, too long, or invalid approval_mode |
| 401 | invalid_token | Token revoked/expired/unknown |
| 403 | insufficient_scope | Token lacks niyra:execute |
| 403 | tool_disabled | Niyra refused to run a tool the user has disabled in Settings → Skills |
| 429 | rate_limit_exceeded | Per-token budget exhausted |
Related
- niyra_get_task — poll a spawned task
- niyra_ask — for "what is X" queries
- Scope catalog
- Rate limits