Documentation
Tasks
tasks.create
REST
ShippingPOST /api/v1/tasks/createMCP tool
Livetasks.createExposed on: REST API · Shop MCP server · Claude connector · Dash (in-app copilot) · Zapier. Part of the Tasks domain.
Operating contract
Adds one to-do to the shop's queue. The title is the only thing required; every other field is an ANCHOR, and a task with anchors is worth several times one without.
ANCHOR IT TO WHAT CAUSED IT. message_id is the strongest: the thread line the task came out of, so whoever picks it up reads the customer's own words rather than your paraphrase of them. conversation files it against the thread, customer_id against the person, job_id against the car. Pass every one you know — they are independent, and the shop's own screens cross-link all four.
ASSIGNING PINGS SOMEBODY. staff_id puts the task in a real person's queue and sends them a notification, so assign when somebody is meant to act rather than as filing. The target must be on tasks.assignees; anyone else is refused rather than silently parked, because a task assigned to someone who cannot open the Tasks tab is work that never happens. Leave it unassigned when it belongs to whoever gets to it first.
due_at IS AN ABSOLUTE INSTANT, and 'tomorrow' has to be resolved against the SHOP's timezone before you call — if you do not know it, ask. An undated task sorts to the bottom of the open block, which is the right place for something that genuinely has no deadline and the wrong place for something that does.
IT IS NOT IDEMPOTENT: calling twice makes two tasks. tasks.list with the same conversation is the cheap check before creating one from a thread you may have already read.
Who may call it
- Permission
inbox.accessThe caller must hold Inbox at the ACT level. A read-only dashboard grant on the same section is refused.- Plan
- Every planNo plan gate. Available on every Service VIN plan.
- Retries
noneA repeat genuinely does it twice and no key can make it not. Read before you write; the operating contract says what to read.- Rate class
writeCounted against the write budget, which is tighter than a read.
Input
| Field | Type | Description |
|---|---|---|
| titlerequired | stringmax 200 chars, min 1 chars | What needs doing, in one line. This is what the shop sees in its queue. |
| notes | stringmax 4000 chars | Any detail that does not fit the title. |
| priority | string | How urgent. Defaults to normal. Default:"normal"One of: low, normal, high |
| due_at | stringmax 40 chars | ISO instant it is due. Resolve 'tomorrow' against the shop's timezone first. |
| conversation | stringuuid | The thread it belongs to, as returned by comms.list_conversations. |
| customer_id | stringuuid | The customer it is about, as returned by customers.list or comms.resolve_contact. |
| job_id | stringuuid | The job it hangs off, as returned by jobs.list. |
| message_id | stringuuid | The thread line that caused it, as returned by comms.list_messages. |
| staff_id | stringuuid | Hand it to this teammate, as returned by tasks.assignees. They are notified. |
Output
| Field | Type | Description |
|---|---|---|
| id | string | — |
| title | string | — |
| notes | string | null | — |
| status | string | — |
| priority | string | — |
| due_at | string | null | — |
| overdue | boolean | — |
| completed_at | string | null | — |
| created_at | string | — |
| conversation | string | null | — |
| conversation_label | string | null | — |
| customer_id | string | null | — |
| job_id | string | null | — |
| message_id | string | null | — |
| assigned_to | string | null | — |
| assignee_name | string | null | — |
Examples
Built from this capability's own schema — required fields and the ones carrying a default, and nothing invented. Paste one and it validates.
export SERVICEVIN_API_KEY=svk_live_…
curl -X POST https://www.servicevin.com/api/v1/tasks/create \
-H "Authorization: Bearer $SERVICEVIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"…","priority":"normal"}'const res = await fetch("https://www.servicevin.com/api/v1/tasks/create", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.SERVICEVIN_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"title": "…",
"priority": "normal"
}),
});
// Success and failure are both envelopes. Switch on error.code, never
// on error.message — the codes are stable, the messages are for people.
const payload = await res.json();
if (!res.ok) throw new Error(payload.error.code);
const data = payload.data;import os, requests
res = requests.post(
"https://www.servicevin.com/api/v1/tasks/create",
headers={"Authorization": f"Bearer {os.environ['SERVICEVIN_API_KEY']}"},
json={
"title": "…",
"priority": "normal"
},
timeout=30,
)
payload = res.json()
if not res.ok:
raise RuntimeError(payload["error"]["code"])
data = payload["data"]{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "tasks.create",
"arguments": {
"title": "…",
"priority": "normal"
}
}
}Refusals
The four gates run in this order on every surface, and the order is not arbitrary — see Authentication.
| Status | Code | When |
|---|---|---|
| 404 | not_found | The id is unknown, or the feature is not enabled for this account. Deliberately the same answer for both. |
| 403 | forbidden | This login does not hold inbox.access. |
| 403 | insufficient_scope | The credential is read-only and this capability writes. |
| 422 | validation_error | An argument was wrong. The message names the field. |
| 429 | rate_limited | Too many write calls. Back off and retry. |
| 500 | internal_error | Something failed on our side. Nothing was changed. |