Docs
Developers

Chat, tasks and workflows

Ask Italic from your own code, decide its drafts, build workflows and set how connected apps ask first.

These endpoints do what Chat, Tasks, Workflows and Connectors do in the Italic apps, with the same checks and limits. Each needs its own permission on the API key; see the permissions table.

Chat

POST /runs asks Italic a question, as the apps' chat does. It needs agent:chat and an Idempotency-Key:

curl https://app.italic.com/api/v2/runs \
  -H "Authorization: Bearer $ITALIC_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: ask-2026-10-22-1' \
  --data '{"message":"What did I promise Sam this week?","timeZone":"America/New_York"}'

The answer is a run, returned as {"run": {…}}:

{
  "run": {
    "id": "8f3b0c6e-2d4a-4c1b-9a57-6e1d2f3a4b5c",
    "source": "chat",
    "status": "completed",
    "reply": "You told Sam you would send the pricing doc by Friday.",
    "actions": [],
    "questions": [],
    "createdAt": 1790121600000,
    "updatedAt": 1790121612000
  }
}

run.reply holds Italic's answer in Markdown once run.status is completed. Italic searches the account's recordings and connected apps, and can draft an email, an event or another action. A draft the account's permissions say to ask about comes back in run.actions with status: "proposed", and the run is awaiting_approval until it is decided. The request answers when the reply is ready, which can take a minute or more.

Italic keeps no conversation for API calls. To follow up, send the earlier turns in history, oldest first. Reusing an Idempotency-Key with the same body returns the first run with replayed: true instead of asking again; keys are kept for 24 hours. If the first request is still running, the retry answers 409 idempotency_in_progress with Retry-After: 5: wait, then send it again. An API key can send ten messages a minute.

Read a run again with GET /runs/{id}. POST /runs/{id}/cancel discards its waiting drafts and ends it.

Tasks

GET /tasks lists what waits for a decision, newest first, as Tasks does in the apps. It answers {"runs": […]}. With agent:chat it lists runs from chat; with actions:review, runs that workflows started (source: "recording").

Tasks in the web app: a calendar event and a reminder drafted from Chat, and an email drafted by a workflow from a Clip, each under the words that started it with its approve, Edit and Discard buttons.
The same runs in Tasks on the web: two from Chat, one from a workflow.

Approve or discard one draft with POST /runs/{id}/actions/{actionId}/decision:

{"decision": "approve", "tool": "send_email"}

decision is approve or reject; reject discards the draft and needs no tool. Approving names the draft's tool, so you approve only what you showed the person; a different tool answers 409 tool_mismatch. Send args to approve an email, event or reminder with edited fields. Italic checks the draft again as the apps do: the app must still be on in Connectors and the fields valid. Approving sends the email or adds the event, so read the returned action's status (succeeded, failed or uncertain). A reminder is approved until the account's iPhone adds it.

A workflow can ask a question instead, listed in questions. Answer it with POST /runs/{id}/questions/{questionId}/answer and one of choice (an index), text, or dismiss: true. This needs agent:chat.

Workflows

GET /workflows and GET /workflows/{id} read workflows (workflows:read). PATCH /workflows/{id} with {"enabled": false} turns one off (workflows:write).

POST /workflows creates one and PUT /workflows/{id} replaces one (workflows:manage). The body is what the builder saves: a name, a trigger and up to eight actions. Italic checks it exactly as the builder does, and an invalid workflow answers 400 with the builder's message.

{
  "name": "Remind me",
  "trigger": {"type": "recording", "phrases": ["remind me"], "match": "start"},
  "actions": [
    {"id": "s1", "type": "create_reminder", "approval": "ask",
     "title": "{{recording.command}}", "notes": "", "due": "", "list": ""}
  ]
}

With "match": "start", {{recording.command}} is what the person said after the phrase; with "anywhere" it is the whole transcript.

POST /workflows needs an Idempotency-Key. A Send webhook action with a new url also needs webhooks:manage; the response's secrets holds its signing secret, which is shown once (a replayed create shows it again). DELETE /workflows/{id} deletes a workflow and stops webhooks no other workflow sends to. An account can have 20 workflows.

Connectors

GET /connectors lists the connected apps with their accounts, and permissions: whether Italic asks first before it acts in each app (ask), acts without asking (allow), or doesn't use it (off). It needs workflows:read or connectors:manage.

With connectors:manage:

  • PUT /connectors/permissions/{tool} sets an app's permission, such as send_email for email.
  • PUT /connectors/permissions/{tool}/accounts/{accountId} gives one email, calendar or Google Drive account its own permission; default uses the app's again.
  • DELETE /connectors/accounts/{id} disconnects a Google, Outlook, Notion or Slack account and revokes Italic's access where the provider allows it.

Connecting an account is a sign-in with the provider, so it happens in the Italic apps, never with an API key. Linear, Granola and Ramp sign-ins and custom connectors are also disconnected in the apps.

On this page