Documentation
Automations
automations.get
REST
ShippingPOST /api/v1/automations/getMCP tool
Liveautomations.getExposed on: REST API · Shop MCP server · Claude connector · Dash (in-app copilot) · Zapier. Part of the Automations domain.
Operating contract
WHAT THIS RULE ACTUALLY DOES, in order: every step, the waits between them, and the words that go out. automations.list says a rule has five steps; this says what those five steps do to a customer.
READ THIS BEFORE ANSWERING ANYTHING ABOUT WHAT A CUSTOMER WAS SENT. A rule's NAME is what somebody typed in a box, and it is routinely wrong about the rule's behaviour — 'Booking reminder' has sent a review request more than once.
customer_facing: true MARKS THE STEPS A REAL PERSON RECEIVES. Those are the ones that clear the compliance rails, and they are the only ones worth reading out when somebody asks what a customer got. A rule made entirely of tags and notes reaches nobody at all — which is a real and frequently surprising finding.
summary IS THE PRODUCT'S OWN DESCRIPTION of the step, including a snippet of the text a customer receives. Quote it rather than paraphrasing a step kind.
TIMING IS IN THE STEPS THEMSELVES. A wait step is a delay in the middle of a sequence, and wait_for_business_hours holds the rest of the rule until the shop is open — which is why a text somebody expected at eight in the evening arrives the next morning and looks like a failure.
stop_if ENDS THE RUN when its conditions match, so every step after it is conditional. A sequence read as though it always completes is a sequence read wrong.
enabled: false on the rule, or the shop's master switch off, means NONE of this runs however good it looks. Both are on the response.
One rule and all of its steps, entirely returned, so nothing is truncated. Editing a rule is a person in the builder: these words are sent to real customers over the shop's own number.
Who may call it
- Permission
shop.manageThe caller must hold shop.manage 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
naturalNaturally idempotent — running it twice leaves the same world as running it once. A retrying integration needs no key.- Rate class
readCounted against the read budget — the widest of the four.
Input
| Field | Type | Description |
|---|---|---|
| automation_idrequired | stringuuid | The rule to read, as returned by automations.list. |
Output
| Field | Type | Description |
|---|---|---|
| id | string | — |
| name | string | — |
| description | string | null | — |
| trigger_type | string | — |
| enabled | boolean | — |
| master_enabled | boolean | — |
| cooldown_days | number | — |
| run_count | number | — |
| last_run_at | string | null | — |
| reaches_customer | boolean | — |
| steps | object[] | — |
| steps[].position | number | — |
| steps[].kind | string | — |
| steps[].label | string | — |
| steps[].group | string | — |
| steps[].customer_facing | boolean | — |
| steps[].summary | string | — |
| unreadable_steps | number | — |
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/automations/get \
-H "Authorization: Bearer $SERVICEVIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"automation_id":"9b2f1c6e-4a77-4d2b-9f31-0f1c9a8e5d20"}'const res = await fetch("https://www.servicevin.com/api/v1/automations/get", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.SERVICEVIN_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"automation_id": "9b2f1c6e-4a77-4d2b-9f31-0f1c9a8e5d20"
}),
});
// 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/automations/get",
headers={"Authorization": f"Bearer {os.environ['SERVICEVIN_API_KEY']}"},
json={
"automation_id": "9b2f1c6e-4a77-4d2b-9f31-0f1c9a8e5d20"
},
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": "automations.get",
"arguments": {
"automation_id": "9b2f1c6e-4a77-4d2b-9f31-0f1c9a8e5d20"
}
}
}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 shop.manage. |
| 422 | validation_error | An argument was wrong. The message names the field. |
| 429 | rate_limited | Too many read calls. Back off and retry. |
| 500 | internal_error | Something failed on our side. Nothing was changed. |