Skip to the documentation
C#

client.Tasks

Every method in this namespace: its signature, its parameters, what it returns and an example.

Methods

Instructions the assistant runs by itself, on a schedule, when mail arrives or when asked: create a task, change, pause, resume and delete it, run it now, hand the assistant a one-off job, follow each run step by step, and approve or deny what a run asks before it acts.

Tasks.ListAsync

List the tasks of the workspace, a page at a time

Scopestasks:readthreads:reademails:readPages through results
Signature
Task<Page> ListAsync(    string? status = null,    int? limit = null,    string? cursor = null,    string? apiKey = null,    CancellationToken cancellationToken = default)

Returns one page of tasks, the most recently changed first. ListAllAsync collects every page and IterateAsync walks them lazily. A task is an instruction in plain words that the assistant runs by itself: on a schedule, when mail arrives, or only when asked. Each one says what starts it in trigger, how much it may do without asking in autonomy, when it runs next in nextRunAt, how its last run ended in lastRunStatus and how many approval requests wait for an answer in pendingApprovals.

Give status: to read only the tasks that are active or only the ones that are paused. pausedReason says why a paused task stopped: user when somebody paused it, failures after 5 failed runs in a row, and plan_limit when the plan no longer covers it.

Parameters

statusstring?

Only tasks in this state: active or paused. Left out, both are listed.

limitint?

Page size, from 1 to 100. The server defaults to 25.

cursorstring?

The nextCursor of the previous page, passed back as it came. Leave it out for the first page.

apiKeystring?

Overrides the client's API key for this call only.

cancellationTokenCancellationToken

Cancels the request.

Returns

A Page with items, hasMore and nextCursor. Each item has id, name, instruction, status, pausedReason, trigger, autonomy, toolkits, model, notify, maxRunsPerDay, maxSteps, nextRunAt, heldUntil, lastRunAt, lastRunStatus, runCount, pendingApprovals, chatId, createdAt and updatedAt.

Example

using OpenEmail.Constants; var page = await client.Tasks.ListAsync(status: TaskStatuses.Active); foreach (var task in page){    Console.WriteLine($"{task["name"]} starts on {task["trigger"]?["kind"]}, next at {task["nextRunAt"]}, {task["pendingApprovals"]} waiting");}

Notes

  • Reading tasks needs threads:read and emails:read beside tasks:read.

  • A task works across every address of the workspace. A key or an app limited to particular addresses or domains is refused with 422 capability_unsupported, and an app acting for a member whose role does not reach every address with 403 owner_only.

  • The order follows updatedAt, which moves when a task changes or starts a run. A workspace holds at most 100 tasks, so limit: 100 reads them all in one request and no task can move between pages.

Also available in

API
GET /tasks
TypeScript
tasks.list()
Python
tasks.list()
Ruby
tasks.list
PHP
tasks->list
Go
Tasks.List
Java
tasks().list
CLI
openemail tasks list

Tasks.ListAllAsync

Collect every task into one list

Scopestasks:readthreads:reademails:readPages through results
Signature
Task<IReadOnlyList<JsonObject>> ListAllAsync(    string? status = null,    int? limit = null,    string? cursor = null,    string? apiKey = null,    CancellationToken cancellationToken = default)

Walks every page of ListAsync and returns all tasks, the most recently changed first. One request per page. Give status: to collect only the active tasks or only the paused ones.

Parameters

statusstring?

Only tasks in this state: active or paused. Left out, both are collected.

limitint?

Page size for each request, from 1 to 100. The server defaults to 25.

cursorstring?

Starts the walk after this cursor instead of the first page.

apiKeystring?

Overrides the client's API key for every page of this walk.

cancellationTokenCancellationToken

Cancels the request in flight and the walk with it.

Returns

A list of JsonObject items holding every task.

Example

var tasks = await client.Tasks.ListAllAsync(limit: 100); foreach (var task in tasks.Where(task => (int?)task["pendingApprovals"] > 0)){    Console.WriteLine($"{task["name"]} waits for {task["pendingApprovals"]} answers");}

Notes

  • If any page fails, the exception is thrown and the tasks already fetched are discarded.

  • A key or an app limited to particular addresses or domains is refused with 422 capability_unsupported, and an app acting for a member whose role does not reach every address with 403 owner_only.

Also available in

API
GET /tasks
TypeScript
tasks.listAll()
Python
tasks.list_all()
Ruby
tasks.list_all
PHP
tasks->listAll
Go
Tasks.ListAll
Java
tasks().listAll

Tasks.IterateAsync

Stream the tasks one at a time

Scopestasks:readthreads:reademails:readPages through results
Signature
IAsyncEnumerable<JsonObject> IterateAsync(    string? status = null,    int? limit = null,    string? cursor = null,    string? apiKey = null,    CancellationToken cancellationToken = default)

Returns an IAsyncEnumerable<JsonObject> that yields tasks one at a time, the most recently changed first, and requests the next page only once the current one is used up. Nothing is fetched until the loop starts, and breaking out of the await foreach stops the requests.

Parameters

statusstring?

Only tasks in this state: active or paused. Left out, both are walked.

limitint?

Page size for each request, from 1 to 100. The server defaults to 25.

cursorstring?

Starts the walk after this cursor instead of the first page.

apiKeystring?

Overrides the client's API key for every page of this walk.

cancellationTokenCancellationToken

Cancels the request in flight and the walk with it.

Returns

An IAsyncEnumerable<JsonObject> that yields one task per step.

Example

using OpenEmail.Constants; await foreach (var task in client.Tasks.IterateAsync(status: TaskStatuses.Paused)){    Console.WriteLine($"{task["name"]} was paused by {task["pausedReason"]}");}

Notes

  • The enumerable is lazy, so an abandoned loop costs only the pages you consumed.

  • A key or an app limited to particular addresses or domains is refused with 422 capability_unsupported, and an app acting for a member whose role does not reach every address with 403 owner_only.

Also available in

API
GET /tasks
TypeScript
tasks.iterate()
Python
tasks.iterate()
Ruby
tasks.iterate
PHP
tasks->iterate
Go
Tasks.Iterate
Java
tasks().iterate

Tasks.GetAsync

Read one task by id

Scopestasks:readthreads:reademails:read
Signature
Task<JsonObject> GetAsync(    string id,    string? apiKey = null,    CancellationToken cancellationToken = default)

Looks up a single task and returns it in the same shape as a row of ListAsync: its instruction, its trigger with the schedule or the mail filter, how much it may do alone, its toolkits and limits, when it runs next and how the last run ended.

nextRunAt is set for an active schedule task and null for the other kinds and while paused. heldUntil is set when the workspace ran out of AI actions for the day: the task starts nothing until then. pendingApprovals counts the approval requests of its runs that still wait for an answer.

Parameters

idstringRequired

Task id such as tsk_5c1e9a7b3d2f48e6a0b4c7d1, as ListAsync returns it.

apiKeystring?

Overrides the client's API key for this call only.

cancellationTokenCancellationToken

Cancels the request.

Returns

A JsonObject with id, name, instruction, status, pausedReason, trigger, autonomy, toolkits, model, notify, maxRunsPerDay, maxSteps, nextRunAt, heldUntil, lastRunAt, lastRunStatus, runCount, pendingApprovals, chatId, createdAt and updatedAt.

Example

var task = await client.Tasks.GetAsync("tsk_5c1e9a7b3d2f48e6a0b4c7d1"); Console.WriteLine($"{task["name"]} is {task["status"]}, starts on {task["trigger"]?["kind"]}, next at {task["nextRunAt"]}");

Notes

  • A missing task throws an OpenEmailApiException whose IsNotFound is true and whose Code is task_not_found.

  • A key or an app limited to particular addresses or domains is refused with 422 capability_unsupported, and an app acting for a member whose role does not reach every address with 403 owner_only.

Also available in

API
GET /tasks/{id}
TypeScript
tasks.get()
Python
tasks.get()
Ruby
tasks.get
PHP
tasks->get
Go
Tasks.Get
Java
tasks().get
CLI
openemail tasks get

Tasks.CreateAsync

Save a task for the assistant to run by itself

Scopestasks:writethreads:readthreads:writeemails:reademails:sendlabels:write
Signature
Task<JsonObject> CreateAsync(    IReadOnlyDictionary<string, object?> body,    string? apiKey = null,    CancellationToken cancellationToken = default)

Saves an instruction for the assistant with what starts it and how much it may do alone, and returns the task as it is stored. instruction says what to do in plain words, as you would tell a person. It is the only instruction a run follows: text inside emails is read, never obeyed.

trigger.kind says what starts a run. A schedule task needs trigger.schedule and gets its first run time at once, in nextRunAt. A mail task starts with the next message that reaches an inbox and matches trigger.mail, or with every message when no filter is sent. Mail from an address of the workspace itself never starts one. A manual task waits for RunAsync.

autonomy limits what a run does without asking. ask sends every change to a person to approve. organize, the default, lets the run label, archive, bin, snooze, draft, take notes and keep contacts by itself, and email the addresses of the workspace. reply also lets it answer an email without asking, as long as it adds no recipients. Anything else waits as an approval request, which ListApprovalsAsync reads. A run never reaches billing, members, roles, domains, rules, keys or webhooks.

A task acts with what its caller holds, so the call needs more than tasks:write: threads:read, threads:write, emails:read, emails:send and labels:write, and the read and write scopes of every toolkit the task names.

Parameters

namestringRequired

What the task is called in the app, trimmed, 1 to 120 characters.

instructionstringRequired

What the assistant should do, in plain words, trimmed, 1 to 8,000 characters.

trigger.kindstringRequired

schedule runs on a clock, mail runs when a message arrives, and manual runs only when started with RunAsync.

trigger.schedule.cadencestring

Needed for a schedule task and ignored for the other kinds. hourly runs every everyHours hours at minute, daily runs at hour:minute on each of weekdays, and monthly runs at hour:minute on monthDay.

trigger.schedule.everyHoursint

For hourly: how many hours lie between runs, from 1 to 12, counted from midnight in the time zone. Defaults to 1.

trigger.schedule.hourint

The hour of the day, 0 to 23, in the time zone of the schedule. Defaults to 8.

trigger.schedule.minuteint

The minute of the hour, 0 to 59. Defaults to 0.

trigger.schedule.weekdayslist

For daily: the days it runs, 0 for Sunday to 6 for Saturday. Left out, it runs every day.

trigger.schedule.monthDayint

For monthly: the day of the month, 1 to 28. Defaults to 1.

trigger.schedule.timezonestring

An IANA time zone such as Europe/Berlin. The schedule follows its clock changes. Defaults to UTC.

trigger.mail.addressesIEnumerable<string>

For a mail task: start only for mail delivered to one of these addresses of the workspace, at most 25. Left out or empty, every address counts.

trigger.mail.fromContainsstring

For a mail task: start only when the sender address contains this text, whatever the case, up to 200 characters.

trigger.mail.subjectContainsstring

For a mail task: start only when the subject contains this text, whatever the case, up to 200 characters.

autonomystring

How much a run may do without asking: ask, organize or reply. Defaults to organize.

toolkitsIEnumerable<string>

Extra groups of tools a run may use beyond reading and organising mail: contacts, audiences, templates, tracking, translate, files, notes, drafts, sent, insights, subscriptions, calendar, knowledge and web. Left out, drafts, notes and knowledge. An empty list gives it none.

modelstring

standard is the everyday model. advanced reasons better over long jobs and costs ten AI actions where the standard one costs one. Defaults to standard.

notifystring

attention notifies the workspace owner when a run waits for approval or fails, always also when it finishes, and never stays silent. Defaults to attention.

maxRunsPerDayint

The most runs the task may start in any 24 hours, however often its trigger fires, from 1 to 500. Defaults to 50.

maxStepsint

The most model steps one run may take before it has to write its report, from 1 to 60. Defaults to 20.

pausedbool

true creates the task paused, so it does not run until ResumeAsync. A paused task does not count against the active tasks of the plan.

apiKeystring?

Overrides the client's API key for this call only.

cancellationTokenCancellationToken

Cancels the request.

Returns

A JsonObject with the new id, status active, or paused when you asked for that, the trigger as it is stored with every default filled in, and nextRunAt set for a schedule.

Example

using OpenEmail.Constants; var task = await client.Tasks.CreateAsync(new Body{    ["name"] = "Label invoices",    ["instruction"] = "When an invoice arrives, label it Invoices and add a note with the amount and the due date.",    ["trigger"] = new Body { ["kind"] = TaskTriggerKinds.Mail, ["mail"] = new Body { ["subjectContains"] = "invoice" } },    ["autonomy"] = TaskAutonomies.Organize,}); Console.WriteLine($"{task["id"]} is {task["status"]}, starts on {task["trigger"]?["kind"]}");

Notes

  • Each toolkit brings its own scopes: contacts needs contacts:read and contacts:write, audiences needs audiences:read, audiences:write and contacts:read, and templates, files, drafts, calendar and knowledge need their read and write scope. The default toolkits therefore need drafts:read, drafts:write, knowledge:read and knowledge:write. A missing scope is a 403 insufficient_scope.

  • A workspace runs 1 active task on Free, 5 on Starter and 25 on Business, with no cap on Enterprise, and holds at most 100 tasks, paused ones included. One more active task than the plan covers is a 403 task_active_limit_reached, and a task past the 100 a 403 task_limit_reached.

  • A schedule trigger without its schedule, a time zone that is not known and a toolkit a task may not use are 422 invalid_task. A value of the wrong type or length is 422 invalid_parameter with param naming it, and a key the body does not take is 422 unknown_parameter.

  • A task works across every address of the workspace. A key or an app limited to particular addresses or domains is refused with 422 capability_unsupported, and an app acting for a member whose role does not reach every address with 403 owner_only.

  • Not retried automatically, and nothing deduplicates by name, so a retry after a lost response can leave two tasks. List them and delete the spare.

Also available in

API
POST /tasks
TypeScript
tasks.create()
Python
tasks.create()
Ruby
tasks.create
PHP
tasks->create
Go
Tasks.Create
Java
tasks().create
CLI
openemail tasks create

Tasks.UpdateAsync

Change what a task does, what starts it or how much it may do alone

Scopestasks:writethreads:readthreads:writeemails:reademails:sendlabels:write
Signature
Task<JsonObject> UpdateAsync(    string id,    IReadOnlyDictionary<string, object?> patch,    string? apiKey = null,    CancellationToken cancellationToken = default)

Changes a task and returns it as it is stored. Send only what changes: a field left out stays as it is, and a patch with nothing in it is a 422.

A new trigger replaces the old one whole. Send its kind and, for a schedule, the whole schedule again, because what the new trigger leaves out goes back to its default, not to what the task had. A schedule change moves nextRunAt of an active task.

Runs already started keep the settings they began with, and later runs follow the new ones. It neither pauses nor resumes a task: PauseAsync and ResumeAsync do that. Like CreateAsync, the call needs the scopes the task acts with, counted from the toolkits it has after the change.

Parameters

idstringRequired

Task id such as tsk_5c1e9a7b3d2f48e6a0b4c7d1, as ListAsync returns it.

namestring

New name, trimmed, 1 to 120 characters. Left out, the name stays.

instructionstring

New instruction in plain words, trimmed, 1 to 8,000 characters. Left out, the instruction stays.

trigger.kindstring

Needed whenever any part of trigger is sent: schedule, mail or manual.

trigger.schedule.cadencestring

Needed for a schedule trigger: hourly, daily or monthly.

trigger.schedule.everyHoursint

For hourly: how many hours lie between runs, from 1 to 12, counted from midnight in the time zone. Defaults to 1.

trigger.schedule.hourint

The hour of the day, 0 to 23, in the time zone of the schedule. Defaults to 8.

trigger.schedule.minuteint

The minute of the hour, 0 to 59. Defaults to 0.

trigger.schedule.weekdayslist

For daily: the days it runs, 0 for Sunday to 6 for Saturday. Left out, it runs every day.

trigger.schedule.monthDayint

For monthly: the day of the month, 1 to 28. Defaults to 1.

trigger.schedule.timezonestring

An IANA time zone such as Europe/Berlin. Defaults to UTC.

trigger.mail.addressesIEnumerable<string>

For a mail trigger: start only for mail delivered to one of these addresses of the workspace, at most 25. Left out or empty, every address counts.

trigger.mail.fromContainsstring

For a mail trigger: start only when the sender address contains this text, whatever the case, up to 200 characters.

trigger.mail.subjectContainsstring

For a mail trigger: start only when the subject contains this text, whatever the case, up to 200 characters.

autonomystring

How much a run may do without asking: ask, organize or reply. Left out, it stays.

toolkitsIEnumerable<string>

The toolkits a run may use from now on, replacing the list the task had. An empty list gives it none. Left out, they stay.

modelstring

standard or advanced, which costs ten AI actions where the standard one costs one. Left out, it stays.

notifystring

When the workspace owner is notified: attention, always or never. Left out, it stays.

maxRunsPerDayint

The most runs the task may start in any 24 hours, from 1 to 500. Left out, it stays.

maxStepsint

The most model steps one run may take, from 1 to 60. Left out, it stays.

apiKeystring?

Overrides the client's API key for this call only.

cancellationTokenCancellationToken

Cancels the request.

Returns

A JsonObject with the unchanged id and status, and everything else as it is now.

Example

using OpenEmail.Constants; var task = await client.Tasks.UpdateAsync("tsk_5c1e9a7b3d2f48e6a0b4c7d1", new Body{    ["trigger"] = new Body    {        ["kind"] = TaskTriggerKinds.Schedule,        ["schedule"] = new Body { ["cadence"] = TaskCadences.Daily, ["hour"] = 8, ["weekdays"] = new[] { 1, 2, 3, 4, 5 }, ["timezone"] = "Europe/Berlin" },    },}); Console.WriteLine($"{task["trigger"]?["schedule"]} runs next at {task["nextRunAt"]}");

Notes

  • A missing task is a 404 task_not_found. An empty patch or a value of the wrong type or length is 422 invalid_parameter, a key the patch does not take 422 unknown_parameter, and a trigger without its schedule, a time zone that is not known or a toolkit a task may not use 422 invalid_task.

  • The key or app needs the read and write scopes of every toolkit the task has after the change, or the call is a 403 insufficient_scope.

  • A key or an app limited to particular addresses or domains is refused with 422 capability_unsupported, and an app acting for a member whose role does not reach every address with 403 owner_only.

  • The SDK retries this call after a network failure, since the same patch sent twice leaves the same task.

Also available in

API
PATCH /tasks/{id}
TypeScript
tasks.update()
Python
tasks.update()
Ruby
tasks.update
PHP
tasks->update
Go
Tasks.Update
Java
tasks().update
CLI
openemail tasks update

Tasks.DeleteAsync

Delete a task with every run it made

Scopestasks:write
Signature
Task<JsonObject> DeleteAsync(    string id,    string? apiKey = null,    CancellationToken cancellationToken = default)

Deletes a task for good, with every run it made and their records. A run in flight is stopped and its open approval requests are closed. What the runs already did in the mailbox stays done.

There is no undo. To stop a task and keep its history, use PauseAsync.

Parameters

idstringRequired

Task id such as tsk_5c1e9a7b3d2f48e6a0b4c7d1, as ListAsync returns it.

apiKeystring?

Overrides the client's API key for this call only.

cancellationTokenCancellationToken

Cancels the request.

Returns

A JsonObject with object set to task, id and deleted set to true.

Example

var removed = await client.Tasks.DeleteAsync("tsk_5c1e9a7b3d2f48e6a0b4c7d1"); Console.WriteLine($"{removed["id"]} deleted: {removed["deleted"]}");

Notes

  • The SDK does not retry a delete. A 404 task_not_found on your own second attempt after a lost response means the first one worked.

  • A key or an app limited to particular addresses or domains is refused with 422 capability_unsupported, and an app acting for a member whose role does not reach every address with 403 owner_only.

Also available in

API
DELETE /tasks/{id}
TypeScript
tasks.delete()
Python
tasks.delete()
Ruby
tasks.delete
PHP
tasks->delete
Go
Tasks.Delete
Java
tasks().delete
CLI
openemail tasks delete

Tasks.PauseAsync

Stop a task from starting new runs

Scopestasks:write
Signature
Task<JsonObject> PauseAsync(    string id,    string? apiKey = null,    CancellationToken cancellationToken = default)

Stops a task from starting new runs: its schedule no longer fires and arriving mail no longer starts it. A run already going carries on, and its approval requests can still be answered. RunAsync still starts a paused task by hand. Pausing a paused task leaves it paused. It takes no body.

Parameters

idstringRequired

Task id such as tsk_5c1e9a7b3d2f48e6a0b4c7d1, as ListAsync returns it.

apiKeystring?

Overrides the client's API key for this call only.

cancellationTokenCancellationToken

Cancels the request.

Returns

A JsonObject with status paused, pausedReason user and nextRunAt null.

Example

var task = await client.Tasks.PauseAsync("tsk_5c1e9a7b3d2f48e6a0b4c7d1"); Console.WriteLine($"{task["status"]} ({task["pausedReason"]})");

Notes

  • A missing task is a 404 task_not_found.

  • To stop a run that is already going, use CancelRunAsync.

  • A key or an app limited to particular addresses or domains is refused with 422 capability_unsupported, and an app acting for a member whose role does not reach every address with 403 owner_only.

  • Retried automatically on network failure and retryable statuses, since pausing twice leaves the same paused task.

Also available in

API
POST /tasks/{id}/pause
TypeScript
tasks.pause()
Python
tasks.pause()
Ruby
tasks.pause
PHP
tasks->pause
Go
Tasks.Pause
Java
tasks().pause
CLI
openemail tasks pause

Tasks.ResumeAsync

Turn a paused task back on

Scopestasks:writethreads:readthreads:writeemails:reademails:sendlabels:write
Signature
Task<JsonObject> ResumeAsync(    string id,    string? apiKey = null,    CancellationToken cancellationToken = default)

Turns a paused task back on, whoever or whatever paused it: a person, 5 failed runs in a row or the plan. It clears the failure count and heldUntil, and gives a schedule task its next run time. A schedule picks up at its next time, and the runs it missed while paused are not made up. It takes no body.

A task acts with what its caller holds, so the call needs the same scopes as CreateAsync: threads:read, threads:write, emails:read, emails:send and labels:write beside tasks:write, and the read and write scopes of every toolkit the task names.

Parameters

idstringRequired

Task id such as tsk_5c1e9a7b3d2f48e6a0b4c7d1, as ListAsync returns it.

apiKeystring?

Overrides the client's API key for this call only.

cancellationTokenCancellationToken

Cancels the request.

Returns

A JsonObject with status active, pausedReason and heldUntil null and, for a schedule, nextRunAt set.

Example

var task = await client.Tasks.ResumeAsync("tsk_5c1e9a7b3d2f48e6a0b4c7d1"); Console.WriteLine($"{task["status"]}, next at {task["nextRunAt"]}");

Notes

  • A plan that covers no more active tasks answers 403 task_active_limit_reached: 1 on Free, 5 on Starter, 25 on Business and no cap on Enterprise. A missing task is a 404 task_not_found.

  • A key or an app without the scopes of a toolkit the task names is refused with 403 insufficient_scope.

  • A key or an app limited to particular addresses or domains is refused with 422 capability_unsupported, and an app acting for a member whose role does not reach every address with 403 owner_only.

  • Retried automatically on network failure and retryable statuses, since resuming twice leaves the same active task.

Also available in

API
POST /tasks/{id}/resume
TypeScript
tasks.resume()
Python
tasks.resume()
Ruby
tasks.resume
PHP
tasks->resume
Go
Tasks.Resume
Java
tasks().resume
CLI
openemail tasks resume

Tasks.RunAsync

Start a run of a task now

Scopestasks:writethreads:readthreads:writeemails:reademails:sendlabels:write
Signature
Task<JsonObject> RunAsync(    string id,    string? apiKey = null,    CancellationToken cancellationToken = default)

Starts a run of a task at once, whatever its trigger and whether or not it is paused, and returns the run as it was queued. The run works in the background. Read it again with GetRunAsync to follow it until status is done, failed or cancelled. While it is waiting, an approval request is open, which ListApprovalsAsync reads.

The run uses the instruction and the settings the task has now, and counts towards its maxRunsPerDay. It takes no body. A task acts with what its caller holds, so the call needs the same scopes as CreateAsync, counted from the toolkits of the task.

Parameters

idstringRequired

Task id such as tsk_5c1e9a7b3d2f48e6a0b4c7d1, as ListAsync returns it.

apiKeystring?

Overrides the client's API key for this call only.

cancellationTokenCancellationToken

Cancels the request.

Returns

A JsonObject with a new id, status queued, trigger manual and the taskId and taskName of the task. transcript and approvals fill in as the run works.

Example

var queued = await client.Tasks.RunAsync("tsk_5c1e9a7b3d2f48e6a0b4c7d1");var run = await client.Tasks.GetRunAsync(queued["id"]!.GetValue<string>()); Console.WriteLine($"{run["status"]}: {run["result"]}");

Notes

  • A task that has started maxRunsPerDay runs in the last 24 hours answers 409 task_run_limit_reached. A missing task is a 404 task_not_found.

  • A key or an app without the scopes of a toolkit the task names is refused with 403 insufficient_scope.

  • A key or an app limited to particular addresses or domains is refused with 422 capability_unsupported, and an app acting for a member whose role does not reach every address with 403 owner_only.

  • Not retried automatically: every call starts another run, so a retry after a lost response can start two. Read ListRunsAsync with taskId: before you try again.

Also available in

API
POST /tasks/{id}/run
TypeScript
tasks.run()
Python
tasks.run()
Ruby
tasks.run
PHP
tasks->run
Go
Tasks.Run
Java
tasks().run
CLI
openemail tasks run

Tasks.ListRunsAsync

List task runs, a page at a time

Scopestasks:readthreads:reademails:readPages through results
Signature
Task<Page> ListRunsAsync(    string? taskId = null,    string? status = null,    int? limit = null,    string? cursor = null,    string? apiKey = null,    CancellationToken cancellationToken = default)

Returns one page of runs, newest first: every run in the workspace, or the runs of one task with taskId:. ListAllRunsAsync collects every page and IterateRunsAsync walks them lazily. A run is one execution. It belongs to a task, named in taskId and taskName, or it is a one-off job started with StartRunAsync, where both are null.

status is queued until a runner picks the run up, running while it works, waiting while an approval request is open, then done, failed or cancelled. result is the report the run wrote when it finished, and error says why a failed run failed. steps, toolCalls and actions count how often the model was asked what to do next, how many tool calls ran and how many AI actions the run has cost the workspace. GetRunAsync adds the record of each step.

Runs are kept for 90 days.

Parameters

taskIdstring?

Only the runs of this task, by its id. Left out, the runs of every task and the one-off runs are listed.

statusstring?

Only runs in this state: queued, running, waiting, done, failed or cancelled.

limitint?

Page size, from 1 to 100. The server defaults to 25.

cursorstring?

The nextCursor of the previous page, passed back as it came. Leave it out for the first page.

apiKeystring?

Overrides the client's API key for this call only.

cancellationTokenCancellationToken

Cancels the request.

Returns

A Page with items, hasMore and nextCursor. Each item has id, taskId, taskName, trigger, threadId, status, instruction, autonomy, model, steps, toolCalls, actions, result, error, errorDetail, pendingApprovals, chatId, createdAt, updatedAt, startedAt and finishedAt.

Example

using OpenEmail.Constants; var page = await client.Tasks.ListRunsAsync(taskId: "tsk_5c1e9a7b3d2f48e6a0b4c7d1", status: TaskRunStatuses.Failed); foreach (var run in page){    Console.WriteLine($"{run["id"]} from {run["createdAt"]} failed with {run["error"]}: {run["errorDetail"]}");}

Notes

  • trigger says what started the run: schedule, mail or manual. A run that mail started names the conversation in threadId.

  • error is ai_limit when the workspace ran out of AI actions for the day, ai_unavailable when AI is not set up, and attempts or no_progress when the run kept failing or stood still. errorDetail adds a sentence about it.

  • A key or an app limited to particular addresses or domains is refused with 422 capability_unsupported, and an app acting for a member whose role does not reach every address with 403 owner_only.

  • The cursor is opaque and holds where the last row sat in this order, so a run that starts between pages never breaks the walk.

Also available in

API
GET /task-runs
TypeScript
tasks.listRuns()
Python
tasks.list_runs()
Ruby
tasks.list_runs
PHP
tasks->listRuns
Go
Tasks.ListRuns
Java
tasks().listRuns
CLI
openemail tasks list-runs

Tasks.ListAllRunsAsync

Collect every task run into one list

Scopestasks:readthreads:reademails:readPages through results
Signature
Task<IReadOnlyList<JsonObject>> ListAllRunsAsync(    string? taskId = null,    string? status = null,    int? limit = null,    string? cursor = null,    string? apiKey = null,    CancellationToken cancellationToken = default)

Follows nextCursor from page to page and returns every run that matches, newest first, in the shape ListRunsAsync returns. limit: sets the page size of each request, not the total. A busy workspace keeps a great many runs for its 90 days, so give taskId: or status:, or prefer IterateRunsAsync when you do not need them all in memory.

Parameters

taskIdstring?

Only the runs of this task, by its id.

statusstring?

Only runs in this state: queued, running, waiting, done, failed or cancelled.

limitint?

Page size for each request, from 1 to 100. The server defaults to 25.

cursorstring?

Starts the walk after this cursor instead of the first page.

apiKeystring?

Overrides the client's API key for every page of this walk.

cancellationTokenCancellationToken

Cancels the request in flight and the walk with it.

Returns

A list of JsonObject items holding every matching run across all pages.

Example

var runs = await client.Tasks.ListAllRunsAsync(taskId: "tsk_5c1e9a7b3d2f48e6a0b4c7d1", limit: 100);var actions = runs.Sum(run => (int?)run["actions"] ?? 0); Console.WriteLine($"{runs.Count} runs cost {actions} AI actions");

Notes

  • If any page fails, the exception is thrown and the runs already fetched are discarded.

  • A key or an app limited to particular addresses or domains is refused with 422 capability_unsupported, and an app acting for a member whose role does not reach every address with 403 owner_only.

Also available in

API
GET /task-runs
TypeScript
tasks.listAllRuns()
Python
tasks.list_all_runs()
Ruby
tasks.list_all_runs
PHP
tasks->listAllRuns
Go
Tasks.ListAllRuns
Java
tasks().listAllRuns

Tasks.IterateRunsAsync

Stream the task runs one at a time

Scopestasks:readthreads:reademails:readPages through results
Signature
IAsyncEnumerable<JsonObject> IterateRunsAsync(    string? taskId = null,    string? status = null,    int? limit = null,    string? cursor = null,    string? apiKey = null,    CancellationToken cancellationToken = default)

Returns an IAsyncEnumerable<JsonObject> that yields runs one at a time, newest first, and requests the next page only once the current one is used up. Nothing is fetched until the loop starts, and breaking out of the await foreach stops the requests.

Parameters

taskIdstring?

Only the runs of this task, by its id.

statusstring?

Only runs in this state: queued, running, waiting, done, failed or cancelled.

limitint?

Page size for each request, from 1 to 100. The server defaults to 25.

cursorstring?

Starts the walk after this cursor instead of the first page.

apiKeystring?

Overrides the client's API key for every page of this walk.

cancellationTokenCancellationToken

Cancels the request in flight and the walk with it.

Returns

An IAsyncEnumerable<JsonObject> that yields one run per step.

Example

using OpenEmail.Constants; await foreach (var run in client.Tasks.IterateRunsAsync(status: TaskRunStatuses.Waiting)){    Console.WriteLine($"{run["id"]} of {run["taskName"]} waits for {run["pendingApprovals"]} answers");}

Notes

  • The enumerable is lazy, so an abandoned loop costs only the pages you consumed.

  • A key or an app limited to particular addresses or domains is refused with 422 capability_unsupported, and an app acting for a member whose role does not reach every address with 403 owner_only.

Also available in

API
GET /task-runs
TypeScript
tasks.iterateRuns()
Python
tasks.iterate_runs()
Ruby
tasks.iterate_runs
PHP
tasks->iterateRuns
Go
Tasks.IterateRuns
Java
tasks().iterateRuns

Tasks.GetRunAsync

Read one run with every step it took

Scopestasks:readthreads:reademails:read
Signature
Task<JsonObject> GetRunAsync(    string id,    string? apiKey = null,    CancellationToken cancellationToken = default)

Returns one run with everything it did: the fields of a row of ListRunsAsync, the record of the run in transcript, in order, and its approval requests in approvals, newest first. steps stays the count it is in ListRunsAsync.

The entry of transcript with role user holds the instruction the run started with. Each entry with role assistant is one step: the text the assistant wrote and calls, the tools it called at that step. A call names its tool as the MCP server lists it, with the args it was called with, done, which is false while the call waits for approval or has not run yet, and result, what the tool answered.

A run is queued, then running, and waiting while an approval request is open. Read it again until it is done, failed or cancelled. result then holds the report it wrote.

Parameters

idstringRequired

Run id such as run_2b8d4f6a1c3e5079b6d8f0a2, as ListRunsAsync returns it.

apiKeystring?

Overrides the client's API key for this call only.

cancellationTokenCancellationToken

Cancels the request.

Returns

A JsonObject with the fields of a row of ListRunsAsync, plus transcript, a list of steps that each have role, text, at and calls, and approvals, a list of approval requests in the shape GetApprovalAsync returns.

Example

var run = await client.Tasks.GetRunAsync("run_2b8d4f6a1c3e5079b6d8f0a2"); foreach (var step in run["transcript"]?.AsArray() ?? []){    foreach (var call in step?["calls"]?.AsArray() ?? [])    {        Console.WriteLine($"{step?["at"]} {call?["tool"]} done: {call?["done"]}");    }} Console.WriteLine($"{run["status"]}: {run["result"]}");

Notes

  • A missing run throws an OpenEmailApiException whose IsNotFound is true and whose Code is task_run_not_found. Runs are kept for 90 days, so an older one is missing too.

  • A key or an app limited to particular addresses or domains is refused with 422 capability_unsupported, and an app acting for a member whose role does not reach every address with 403 owner_only.

  • Read only, so the SDK retries it after a network failure like any other read.

Also available in

API
GET /task-runs/{id}
TypeScript
tasks.getRun()
Python
tasks.get_run()
Ruby
tasks.get_run
PHP
tasks->getRun
Go
Tasks.GetRun
Java
tasks().getRun
CLI
openemail tasks get-run

Tasks.StartRunAsync

Hand the assistant a one-off job to do in the background

Scopestasks:writethreads:readthreads:writeemails:reademails:sendlabels:write
Signature
Task<JsonObject> StartRunAsync(    IReadOnlyDictionary<string, object?> body,    string? apiKey = null,    CancellationToken cancellationToken = default)

Hands the assistant one job to do in the background, with no task saved: a long tidy-up, a report, or anything that should not wait on an open chat. It returns the run as it was queued. Follow it with GetRunAsync, and answer what it asks with ApproveAsync or DenyAsync.

instruction is the whole job, in plain words. threadId hands the run one conversation as its starting point. autonomy, toolkits, model and maxSteps mean what they mean on a task and take the same defaults. The workspace owner is notified when the run waits for approval or fails.

A workspace starts at most 100 of these in any 24 hours. A run acts with what its caller holds, so the call needs the same scopes as CreateAsync: threads:read, threads:write, emails:read, emails:send and labels:write beside tasks:write, and the read and write scopes of every toolkit it names.

Parameters

instructionstringRequired

What the assistant should do, in plain words, trimmed, 1 to 8,000 characters. It is the only instruction the run follows: text inside emails is read, never obeyed.

autonomystring

How much the run may do without asking: ask, organize or reply. Defaults to organize.

toolkitsIEnumerable<string>

Extra groups of tools the run may use beyond reading and organising mail, such as contacts, calendar, knowledge or web. Left out, drafts, notes and knowledge. An empty list gives it none.

modelstring

standard is the everyday model. advanced reasons better over long jobs and costs ten AI actions where the standard one costs one. Defaults to standard.

maxStepsint

The most model steps the run may take before it has to write its report, from 1 to 60. Defaults to 20.

threadIdstring

A conversation to hand the run as its starting point, by the id Threads.ListAsync returns.

apiKeystring?

Overrides the client's API key for this call only.

cancellationTokenCancellationToken

Cancels the request.

Returns

A JsonObject with a new id, status queued, trigger manual, and taskId and taskName null. transcript and approvals fill in as the run works.

Example

using OpenEmail.Constants; var queued = await client.Tasks.StartRunAsync(new Body{    ["instruction"] = "Find every invoice that arrived this month and label it Invoices.",    ["autonomy"] = TaskAutonomies.Organize,    ["maxSteps"] = 30,}); Console.WriteLine($"{queued["id"]} is {queued["status"]}");

Notes

  • Past 100 one-off runs in 24 hours the call answers 409 task_run_limit_reached.

  • A toolkit a run may not use is 422 invalid_task, a value of the wrong type or length 422 invalid_parameter with param naming it, and a key the body does not take 422 unknown_parameter. A missing scope of a toolkit is a 403 insufficient_scope.

  • A key or an app limited to particular addresses or domains is refused with 422 capability_unsupported, and an app acting for a member whose role does not reach every address with 403 owner_only.

  • Not retried automatically: every call starts another run, so a retry after a lost response can start two. Read ListRunsAsync before you try again.

Also available in

API
POST /task-runs
TypeScript
tasks.startRun()
Python
tasks.start_run()
Ruby
tasks.start_run
PHP
tasks->startRun
Go
Tasks.StartRun
Java
tasks().startRun
CLI
openemail tasks start-run

Tasks.CancelRunAsync

Stop a run that has not ended

Scopestasks:write
Signature
Task<JsonObject> CancelRunAsync(    string id,    string? apiKey = null,    CancellationToken cancellationToken = default)

Stops a run that is queued, running or waiting for approval, and closes its open approval requests, which become cancelled. What the run already did stays done: nothing is rolled back. The task it belongs to is left as it is and runs again when its trigger next fires. It takes no body.

Parameters

idstringRequired

Run id such as run_2b8d4f6a1c3e5079b6d8f0a2, as ListRunsAsync returns it.

apiKeystring?

Overrides the client's API key for this call only.

cancellationTokenCancellationToken

Cancels the request.

Returns

A JsonObject with status cancelled and finishedAt set, and transcript showing how far it got.

Example

var run = await client.Tasks.CancelRunAsync("run_2b8d4f6a1c3e5079b6d8f0a2"); Console.WriteLine($"{run["status"]} at {run["finishedAt"]} after {run["toolCalls"]} tool calls");

Notes

  • A run that has already ended answers 409 task_run_finished, and a missing one 404 task_run_not_found.

  • To keep a task from starting more runs, use PauseAsync.

  • A key or an app limited to particular addresses or domains is refused with 422 capability_unsupported, and an app acting for a member whose role does not reach every address with 403 owner_only.

  • Not retried automatically. A 409 task_run_finished on your own second attempt after a lost response means the first one worked or the run ended by itself, and GetRunAsync says which.

Also available in

API
POST /task-runs/{id}/cancel
TypeScript
tasks.cancelRun()
Python
tasks.cancel_run()
Ruby
tasks.cancel_run
PHP
tasks->cancelRun
Go
Tasks.CancelRun
Java
tasks().cancelRun
CLI
openemail tasks cancel-run

Tasks.ListApprovalsAsync

List what runs are waiting for a person to allow

Scopestasks:readthreads:reademails:readPages through results
Signature
Task<Page> ListApprovalsAsync(    string? status = null,    string? runId = null,    string? taskId = null,    int? limit = null,    string? cursor = null,    string? apiKey = null,    CancellationToken cancellationToken = default)

Returns one page of approval requests, newest first. An approval request is a tool call a run stopped at because it may not make it alone: tool names the tool, summary says in one line what would happen, and args holds the exact arguments it would be called with. A reply shows the recipients worked out from the message it answers.

Without status: the list holds only the requests still pending. Give it to read the ones that were approved, denied, expired or cancelled, and runId: or taskId: to read those of one run or of one task. ListAllApprovalsAsync collects every page and IterateApprovalsAsync walks them lazily.

A request waits 7 days. Then it expires and the run carries on without it. Answer one with ApproveAsync or DenyAsync.

Parameters

statusstring?

Only requests in this state: pending, approved, denied, expired or cancelled. Left out, the list holds the ones still pending.

runIdstring?

Only the requests of this run, by its id.

taskIdstring?

Only the requests of the runs of this task, by its id.

limitint?

Page size, from 1 to 100. The server defaults to 25.

cursorstring?

The nextCursor of the previous page, passed back as it came. Leave it out for the first page.

apiKeystring?

Overrides the client's API key for this call only.

cancellationTokenCancellationToken

Cancels the request.

Returns

A Page with items, hasMore and nextCursor. Each item has id, runId, taskId, taskName, tool, summary, args, status, createdAt, expiresAt and decidedAt.

Example

var page = await client.Tasks.ListApprovalsAsync(); foreach (var approval in page){    Console.WriteLine($"{approval["id"]} from {approval["taskName"]}: {approval["summary"]}, until {approval["expiresAt"]}");}

Notes

  • No value of status: means the requests still pending. Read each other state in turn to see the rest.

  • taskId and taskName are null on a request of a one-off run.

  • A key or an app limited to particular addresses or domains is refused with 422 capability_unsupported, and an app acting for a member whose role does not reach every address with 403 owner_only.

Also available in

API
GET /task-approvals
TypeScript
tasks.listApprovals()
Python
tasks.list_approvals()
Ruby
tasks.list_approvals
PHP
tasks->listApprovals
Go
Tasks.ListApprovals
Java
tasks().listApprovals
CLI
openemail tasks list-approvals

Tasks.ListAllApprovalsAsync

Collect every approval request into one list

Scopestasks:readthreads:reademails:readPages through results
Signature
Task<IReadOnlyList<JsonObject>> ListAllApprovalsAsync(    string? status = null,    string? runId = null,    string? taskId = null,    int? limit = null,    string? cursor = null,    string? apiKey = null,    CancellationToken cancellationToken = default)

Walks every page of ListApprovalsAsync and returns all the requests that match, newest first. One request per page. Without status: it collects only the requests still pending, which is the list a person has to answer.

Parameters

statusstring?

Only requests in this state: pending, approved, denied, expired or cancelled. Left out, the ones still pending are collected.

runIdstring?

Only the requests of this run, by its id.

taskIdstring?

Only the requests of the runs of this task, by its id.

limitint?

Page size for each request, from 1 to 100. The server defaults to 25.

cursorstring?

Starts the walk after this cursor instead of the first page.

apiKeystring?

Overrides the client's API key for every page of this walk.

cancellationTokenCancellationToken

Cancels the request in flight and the walk with it.

Returns

A list of JsonObject items holding every matching request.

Example

var pending = await client.Tasks.ListAllApprovalsAsync(runId: "run_2b8d4f6a1c3e5079b6d8f0a2"); foreach (var approval in pending){    Console.WriteLine($"{approval["tool"]}: {approval["summary"]}");}

Notes

  • If any page fails, the exception is thrown and the requests already fetched are discarded.

  • A key or an app limited to particular addresses or domains is refused with 422 capability_unsupported, and an app acting for a member whose role does not reach every address with 403 owner_only.

Also available in

API
GET /task-approvals
TypeScript
tasks.listAllApprovals()
Python
tasks.list_all_approvals()
Ruby
tasks.list_all_approvals
PHP
tasks->listAllApprovals
Go
Tasks.ListAllApprovals
Java
tasks().listAllApprovals

Tasks.IterateApprovalsAsync

Stream the approval requests one at a time

Scopestasks:readthreads:reademails:readPages through results
Signature
IAsyncEnumerable<JsonObject> IterateApprovalsAsync(    string? status = null,    string? runId = null,    string? taskId = null,    int? limit = null,    string? cursor = null,    string? apiKey = null,    CancellationToken cancellationToken = default)

Returns an IAsyncEnumerable<JsonObject> that yields approval requests one at a time, newest first, and requests the next page only once the current one is used up. Without status: it yields only the requests still pending. Nothing is fetched until the loop starts, and breaking out of the await foreach stops the requests.

Parameters

statusstring?

Only requests in this state: pending, approved, denied, expired or cancelled. Left out, the ones still pending are walked.

runIdstring?

Only the requests of this run, by its id.

taskIdstring?

Only the requests of the runs of this task, by its id.

limitint?

Page size for each request, from 1 to 100. The server defaults to 25.

cursorstring?

Starts the walk after this cursor instead of the first page.

apiKeystring?

Overrides the client's API key for every page of this walk.

cancellationTokenCancellationToken

Cancels the request in flight and the walk with it.

Returns

An IAsyncEnumerable<JsonObject> that yields one approval request per step.

Example

await foreach (var approval in client.Tasks.IterateApprovalsAsync(taskId: "tsk_5c1e9a7b3d2f48e6a0b4c7d1")){    Console.WriteLine($"{approval["id"]} {approval["tool"]}: {approval["summary"]}");}

Notes

  • The enumerable is lazy, so an abandoned loop costs only the pages you consumed.

  • A key or an app limited to particular addresses or domains is refused with 422 capability_unsupported, and an app acting for a member whose role does not reach every address with 403 owner_only.

Also available in

API
GET /task-approvals
TypeScript
tasks.iterateApprovals()
Python
tasks.iterate_approvals()
Ruby
tasks.iterate_approvals
PHP
tasks->iterateApprovals
Go
Tasks.IterateApprovals
Java
tasks().iterateApprovals

Tasks.GetApprovalAsync

Read one approval request by id

Scopestasks:readthreads:reademails:read
Signature
Task<JsonObject> GetApprovalAsync(    string id,    string? apiKey = null,    CancellationToken cancellationToken = default)

Looks up a single approval request and returns it in the same shape as a row of ListApprovalsAsync: the run that asked and its task, the tool the run wants to call, the one-line summary, the exact args and its status. args are what will be done once it is approved, unless ApproveAsync replaces the subject or the words of a send or a reply.

Parameters

idstringRequired

Approval request id such as apr_9f3a1c5e7b2d4608a1c3e5f7, as ListApprovalsAsync returns it.

apiKeystring?

Overrides the client's API key for this call only.

cancellationTokenCancellationToken

Cancels the request.

Returns

A JsonObject with id, runId, taskId, taskName, tool, summary, args, status, createdAt, expiresAt and decidedAt.

Example

var approval = await client.Tasks.GetApprovalAsync("apr_9f3a1c5e7b2d4608a1c3e5f7"); Console.WriteLine($"{approval["tool"]}: {approval["summary"]} {approval["args"]}");

Notes

  • A missing request throws an OpenEmailApiException whose IsNotFound is true and whose Code is task_approval_not_found.

  • taskId and taskName are null on a request of a one-off run.

  • A key or an app limited to particular addresses or domains is refused with 422 capability_unsupported, and an app acting for a member whose role does not reach every address with 403 owner_only.

Also available in

API
GET /task-approvals/{id}
TypeScript
tasks.getApproval()
Python
tasks.get_approval()
Ruby
tasks.get_approval
PHP
tasks->getApproval
Go
Tasks.GetApproval
Java
tasks().getApproval
CLI
openemail tasks get-approval

Tasks.ApproveAsync

Let a run do what it asked for

Scopestasks:writethreads:readthreads:writeemails:reademails:sendlabels:write
Signature
Task<JsonObject> ApproveAsync(    string id,    IReadOnlyDictionary<string, object?>? body = null,    string? apiKey = null,    CancellationToken cancellationToken = default)

Approves a pending request, so the run makes the tool call with the arguments the request shows. For a send or a reply, subject and body replace what the run wrote, and the answer shows the changed args. For any other tool they are ignored. Call it with the id alone to approve the request as it stands.

The run picks up again once every request of its step is answered, so a run that asked for three things waits for three answers. A task acts with what its caller holds, so approving needs the scopes the run works with: the same as CreateAsync, counted from the toolkits of its task.

Parameters

idstringRequired

Approval request id such as apr_9f3a1c5e7b2d4608a1c3e5f7, as ListApprovalsAsync returns it.

subjectstring

For a send or a reply: the subject to use instead of the one the run wrote, trimmed, 1 to 998 characters.

bodystring

For a send or a reply: the words to send instead of the ones the run wrote, trimmed, 1 to 100,000 characters.

apiKeystring?

Overrides the client's API key for this call only.

cancellationTokenCancellationToken

Cancels the request.

Returns

A JsonObject with status approved, decidedAt set and args as the tool will be called with them.

Example

var approval = await client.Tasks.ApproveAsync("apr_9f3a1c5e7b2d4608a1c3e5f7", new Body { ["subject"] = "Your refund is on its way" }); Console.WriteLine($"{approval["status"]} at {approval["decidedAt"]}");

Notes

  • A request that was already answered, has expired, or whose run has ended answers 409 task_approval_decided. A missing one is a 404 task_approval_not_found.

  • There is no undo once the run has acted, so read args first.

  • A key or an app without the scopes of a toolkit the task names is refused with 403 insufficient_scope, and a key the body does not take is 422 unknown_parameter.

  • A key or an app limited to particular addresses or domains is refused with 422 capability_unsupported, and an app acting for a member whose role does not reach every address with 403 owner_only.

  • The SDK does not retry it. A 409 task_approval_decided on your own second attempt after a lost response means the first one worked or somebody else answered, and GetApprovalAsync says how.

Also available in

API
POST /task-approvals/{id}/approve
TypeScript
tasks.approve()
Python
tasks.approve()
Ruby
tasks.approve
PHP
tasks->approve
Go
Tasks.Approve
Java
tasks().approve
CLI
openemail tasks approve

Tasks.DenyAsync

Refuse what a run asked for

Scopestasks:write
Signature
Task<JsonObject> DenyAsync(    string id,    string? apiKey = null,    CancellationToken cancellationToken = default)

Denies a pending request. The run is told, does not try that call again, and carries on with the rest of its task once every request of its step is answered. Nothing the request described is done. It takes no body.

Parameters

idstringRequired

Approval request id such as apr_9f3a1c5e7b2d4608a1c3e5f7, as ListApprovalsAsync returns it.

apiKeystring?

Overrides the client's API key for this call only.

cancellationTokenCancellationToken

Cancels the request.

Returns

A JsonObject with status denied and decidedAt set.

Example

var approval = await client.Tasks.DenyAsync("apr_9f3a1c5e7b2d4608a1c3e5f7"); Console.WriteLine($"{approval["status"]}, {approval["tool"]} was not run");

Notes

  • A request that was already answered, has expired, or whose run has ended answers 409 task_approval_decided. A missing one is a 404 task_approval_not_found.

  • To stop the whole run instead of one request, use CancelRunAsync.

  • A key or an app limited to particular addresses or domains is refused with 422 capability_unsupported, and an app acting for a member whose role does not reach every address with 403 owner_only.

  • The SDK does not retry it. A 409 task_approval_decided on your own second attempt after a lost response means the first one worked or somebody else answered, and GetApprovalAsync says how.

Also available in

API
POST /task-approvals/{id}/deny
TypeScript
tasks.deny()
Python
tasks.deny()
Ruby
tasks.deny
PHP
tasks->deny
Go
Tasks.Deny
Java
tasks().deny
CLI
openemail tasks deny