Automation rules
An automation rule gives a category, labels and a note to the transactions that meet its conditions. Rules are evaluated in priority order, lowest first, and a new transaction gets the actions of the first rule it matches and no other. A rule only runs on transactions created after it: run it over the ones already there with the apply endpoint.
The example requests read your personal token from $WHISPER_MONEY_TOKEN: run export WHISPER_MONEY_TOKEN=wm_api_your_token_here before pasting them.
List automation rules
GET /api/v1/automation-rules
Your rules in a space in the order they are evaluated: priority ascending, then title. As in the app, another member's rules are not listed.
Scope: read. A personal token needs api:read; an OAuth token needs api:use.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
limit |
query | integer | No | How many objects to return, between 1 and 100. Defaults to 25. |
starting_after |
query | string (uuid) | No | An object id: return the page that follows it. Pass the last id of the page you have. |
ending_before |
query | string (uuid) | No | An object id: return the page that precedes it. Pass the first id of the page you have. Cannot be combined with starting_after. |
space |
query | string (uuid) | No | The id of the space to work in (see GET /spaces). Defaults to your personal space. On writes it may also be sent in the JSON body. |
Response
200
| Field | Type | Description |
|---|---|---|
data |
array of AutomationRule | |
data[].id |
string (uuid) | The rule's id. |
data[].space_id |
string (uuid) or null | The id of the space the rule is in. |
data[].title |
string | The rule's name. |
data[].priority |
integer | The order the rule is evaluated in, lowest first. A new transaction gets the actions of the first rule it matches, and no other. |
data[].conditions |
object | The conditions a transaction must meet, as one JsonLogic object. Amounts in here are in MAJOR units, unlike every other amount in the API. A rule the AI categorization learned can still have none: {}. |
data[].action_category_id |
string (uuid) or null | The id of the category the rule gives the matching transactions, or null for none. |
data[].action_label_ids |
array of string | The ids of the labels the rule adds to the matching transactions. |
data[].action_note |
string or null | The note the rule appends to the matching transactions' notes, or null for none. |
data[].origin |
"user" | "ai" | "correction" | Who made the rule: user for one made by hand (in the app, the AI connector or this API), ai for one Whisper Money's AI categorization learned, and correction for one it learned from your own recategorizations. |
data[].created_at |
string (date-time) or null | When the rule was created. |
data[].updated_at |
string (date-time) or null | When the rule was last changed. |
has_more |
boolean | Whether more objects exist past this page, in the direction being walked. |
Example request
curl https://whisper.money/api/v1/automation-rules \
-H "Authorization: Bearer $WHISPER_MONEY_TOKEN"
Example response
{
"data": [
{
"id": "0199a3f9-5d6e-7f8a-9b0c-1d2e3f4a5b6c",
"space_id": "0199a3f2-6c1e-7b4d-9a8e-2f5c1d3b4a60",
"title": "Groceries",
"priority": 10,
"conditions": {
"and": [
{
"in": [
"mercadona",
{
"var": "description"
}
]
},
{
"<": [
{
"var": "amount"
},
0
]
}
]
},
"action_category_id": "0199a3f5-2b3c-7d4e-8f5a-6b7c8d9e0f12",
"action_label_ids": [
"0199a3f6-3c4d-7e5f-9a6b-7c8d9e0f1a23"
],
"action_note": "Weekly shop",
"origin": "user",
"created_at": "2026-01-15T09:30:00+00:00",
"updated_at": "2026-01-20T18:05:00+00:00"
}
],
"has_more": true
}
Errors
| Status | When |
|---|---|
400 |
A malformed request: an unknown pagination cursor (invalid_cursor) or an invalid Idempotency-Key (invalid_idempotency_key). |
401 |
No bearer token, or one that is unknown, expired or revoked. |
403 |
The token lacks the scope (insufficient_scope), the account has no Pro plan (plan_required, with a subscribe_url) or it is a shared demo account (shared_account). |
422 |
The request failed validation. |
429 |
The rate limit is exhausted. Wait the seconds in Retry-After. |
Create an automation rule
POST /api/v1/automation-rules
The rule needs at least one action: action_category_id, action_label_ids or both. It only runs on the transactions created from now on. Conditions that say something other than what you meant still save and then quietly match nothing, so preview a new rule with the apply endpoint before trusting it.
Scope: write. A personal token needs api:write (a read & write token); an OAuth token needs api:use.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
space |
query | string (uuid) | No | The id of the space to work in (see GET /spaces). Defaults to your personal space. On writes it may also be sent in the JSON body. |
Idempotency-Key |
header | string | No | Any unique string up to 255 characters. Retrying with the same key within 24 hours returns the first response instead of repeating the request. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
title |
string | Yes | The rule's name. |
priority |
integer | Yes | The order the rule is evaluated in, lowest first. A new transaction gets the actions of the first rule it matches, and no other. |
conditions |
object | Yes | The conditions a transaction must meet, as one JsonLogic object. Amounts in here are in MAJOR units (12.50), unlike every other amount in the API, and signed: an expense is negative. Text is compared lowercased, so write values in lowercase. Only these operators are accepted: and, or, !, ==, !=, >, >=, <, <=, in and var; and only these variables: description, notes, creditor_name, debtor_name, account_name, bank_name, category, transaction_date (YYYY-MM-DD) and amount. "Contains" is {"in": ["netflix", {"var": "description"}]}, a negation wraps a condition in !, and and / or take a list and nest freely. "Is not" and "does not contain" also match a transaction whose field is empty. |
action_category_id |
string (uuid) or null | No | The id of the category to give the matching transactions, one of your categories in the space, or null for none. A rule needs a category, labels or both. |
action_label_ids |
array of string (uuid) | No | The ids of the labels to add to the matching transactions, each one of your labels in the space, 50 at most. On update the list replaces the rule's labels; an empty one removes them all. |
action_note |
string or null | No | A note to append to the matching transactions' notes, or null for none. |
Response
201
| Field | Type | Description |
|---|---|---|
data |
AutomationRule | |
data.id |
string (uuid) | The rule's id. |
data.space_id |
string (uuid) or null | The id of the space the rule is in. |
data.title |
string | The rule's name. |
data.priority |
integer | The order the rule is evaluated in, lowest first. A new transaction gets the actions of the first rule it matches, and no other. |
data.conditions |
object | The conditions a transaction must meet, as one JsonLogic object. Amounts in here are in MAJOR units, unlike every other amount in the API. A rule the AI categorization learned can still have none: {}. |
data.action_category_id |
string (uuid) or null | The id of the category the rule gives the matching transactions, or null for none. |
data.action_label_ids |
array of string | The ids of the labels the rule adds to the matching transactions. |
data.action_note |
string or null | The note the rule appends to the matching transactions' notes, or null for none. |
data.origin |
"user" | "ai" | "correction" | Who made the rule: user for one made by hand (in the app, the AI connector or this API), ai for one Whisper Money's AI categorization learned, and correction for one it learned from your own recategorizations. |
data.created_at |
string (date-time) or null | When the rule was created. |
data.updated_at |
string (date-time) or null | When the rule was last changed. |
Example request
curl -X POST https://whisper.money/api/v1/automation-rules \
-H "Authorization: Bearer $WHISPER_MONEY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Groceries",
"priority": 10,
"conditions": {
"and": [
{
"in": [
"mercadona",
{
"var": "description"
}
]
},
{
"<": [
{
"var": "amount"
},
0
]
}
]
},
"action_label_ids": [
"0199a3f6-3c4d-7e5f-9a6b-7c8d9e0f1a23"
],
"action_note": "Weekly shop"
}'
Example response
{
"data": {
"id": "0199a3f9-5d6e-7f8a-9b0c-1d2e3f4a5b6c",
"space_id": "0199a3f2-6c1e-7b4d-9a8e-2f5c1d3b4a60",
"title": "Groceries",
"priority": 10,
"conditions": {
"and": [
{
"in": [
"mercadona",
{
"var": "description"
}
]
},
{
"<": [
{
"var": "amount"
},
0
]
}
]
},
"action_category_id": "0199a3f5-2b3c-7d4e-8f5a-6b7c8d9e0f12",
"action_label_ids": [
"0199a3f6-3c4d-7e5f-9a6b-7c8d9e0f1a23"
],
"action_note": "Weekly shop",
"origin": "user",
"created_at": "2026-01-15T09:30:00+00:00",
"updated_at": "2026-01-20T18:05:00+00:00"
}
}
Errors
| Status | When |
|---|---|
400 |
A malformed request: an unknown pagination cursor (invalid_cursor) or an invalid Idempotency-Key (invalid_idempotency_key). |
401 |
No bearer token, or one that is unknown, expired or revoked. |
403 |
The token lacks the scope (insufficient_scope), the account has no Pro plan (plan_required, with a subscribe_url) or it is a shared demo account (shared_account). |
409 |
A request with the same Idempotency-Key is still being processed. |
422 |
The request failed validation. |
429 |
The rate limit is exhausted. Wait the seconds in Retry-After. |
Retrieve an automation rule
GET /api/v1/automation-rules/{automation_rule}
Scope: read. A personal token needs api:read; an OAuth token needs api:use.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
automation_rule |
path | string (uuid) | Yes | The rule's id. |
space |
query | string (uuid) | No | The id of the space to work in (see GET /spaces). Defaults to your personal space. On writes it may also be sent in the JSON body. |
Response
200
| Field | Type | Description |
|---|---|---|
data |
AutomationRule | |
data.id |
string (uuid) | The rule's id. |
data.space_id |
string (uuid) or null | The id of the space the rule is in. |
data.title |
string | The rule's name. |
data.priority |
integer | The order the rule is evaluated in, lowest first. A new transaction gets the actions of the first rule it matches, and no other. |
data.conditions |
object | The conditions a transaction must meet, as one JsonLogic object. Amounts in here are in MAJOR units, unlike every other amount in the API. A rule the AI categorization learned can still have none: {}. |
data.action_category_id |
string (uuid) or null | The id of the category the rule gives the matching transactions, or null for none. |
data.action_label_ids |
array of string | The ids of the labels the rule adds to the matching transactions. |
data.action_note |
string or null | The note the rule appends to the matching transactions' notes, or null for none. |
data.origin |
"user" | "ai" | "correction" | Who made the rule: user for one made by hand (in the app, the AI connector or this API), ai for one Whisper Money's AI categorization learned, and correction for one it learned from your own recategorizations. |
data.created_at |
string (date-time) or null | When the rule was created. |
data.updated_at |
string (date-time) or null | When the rule was last changed. |
Example request
curl https://whisper.money/api/v1/automation-rules/0199a3f2-6c1e-7b4d-9a8e-2f5c1d3b4a60 \
-H "Authorization: Bearer $WHISPER_MONEY_TOKEN"
Example response
{
"data": {
"id": "0199a3f9-5d6e-7f8a-9b0c-1d2e3f4a5b6c",
"space_id": "0199a3f2-6c1e-7b4d-9a8e-2f5c1d3b4a60",
"title": "Groceries",
"priority": 10,
"conditions": {
"and": [
{
"in": [
"mercadona",
{
"var": "description"
}
]
},
{
"<": [
{
"var": "amount"
},
0
]
}
]
},
"action_category_id": "0199a3f5-2b3c-7d4e-8f5a-6b7c8d9e0f12",
"action_label_ids": [
"0199a3f6-3c4d-7e5f-9a6b-7c8d9e0f1a23"
],
"action_note": "Weekly shop",
"origin": "user",
"created_at": "2026-01-15T09:30:00+00:00",
"updated_at": "2026-01-20T18:05:00+00:00"
}
}
Errors
| Status | When |
|---|---|
401 |
No bearer token, or one that is unknown, expired or revoked. |
403 |
The token lacks the scope (insufficient_scope), the account has no Pro plan (plan_required, with a subscribe_url) or it is a shared demo account (shared_account). |
404 |
No object with that id exists, or it belongs to someone else. |
422 |
The request failed validation. |
429 |
The rate limit is exhausted. Wait the seconds in Retry-After. |
Update an automation rule
PATCH /api/v1/automation-rules/{automation_rule}
Changes only the fields you send. conditions and action_label_ids replace the rule's whole set. The rule must keep at least one action, a category or labels: leaving it without one is a 422 under action_category_id. The transactions it already touched keep what it gave them.
Scope: write. A personal token needs api:write (a read & write token); an OAuth token needs api:use.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
automation_rule |
path | string (uuid) | Yes | The rule's id. |
space |
query | string (uuid) | No | The id of the space to work in (see GET /spaces). Defaults to your personal space. On writes it may also be sent in the JSON body. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
title |
string | No | The rule's name. |
priority |
integer | No | The order the rule is evaluated in, lowest first. A new transaction gets the actions of the first rule it matches, and no other. |
conditions |
object | No | The conditions a transaction must meet, as one JsonLogic object. Amounts in here are in MAJOR units (12.50), unlike every other amount in the API, and signed: an expense is negative. Text is compared lowercased, so write values in lowercase. Only these operators are accepted: and, or, !, ==, !=, >, >=, <, <=, in and var; and only these variables: description, notes, creditor_name, debtor_name, account_name, bank_name, category, transaction_date (YYYY-MM-DD) and amount. "Contains" is {"in": ["netflix", {"var": "description"}]}, a negation wraps a condition in !, and and / or take a list and nest freely. "Is not" and "does not contain" also match a transaction whose field is empty. |
action_category_id |
string (uuid) or null | No | The id of the category to give the matching transactions, one of your categories in the space, or null for none. A rule needs a category, labels or both. |
action_label_ids |
array of string (uuid) | No | The ids of the labels to add to the matching transactions, each one of your labels in the space, 50 at most. On update the list replaces the rule's labels; an empty one removes them all. |
action_note |
string or null | No | A note to append to the matching transactions' notes, or null for none. |
Response
200
| Field | Type | Description |
|---|---|---|
data |
AutomationRule | |
data.id |
string (uuid) | The rule's id. |
data.space_id |
string (uuid) or null | The id of the space the rule is in. |
data.title |
string | The rule's name. |
data.priority |
integer | The order the rule is evaluated in, lowest first. A new transaction gets the actions of the first rule it matches, and no other. |
data.conditions |
object | The conditions a transaction must meet, as one JsonLogic object. Amounts in here are in MAJOR units, unlike every other amount in the API. A rule the AI categorization learned can still have none: {}. |
data.action_category_id |
string (uuid) or null | The id of the category the rule gives the matching transactions, or null for none. |
data.action_label_ids |
array of string | The ids of the labels the rule adds to the matching transactions. |
data.action_note |
string or null | The note the rule appends to the matching transactions' notes, or null for none. |
data.origin |
"user" | "ai" | "correction" | Who made the rule: user for one made by hand (in the app, the AI connector or this API), ai for one Whisper Money's AI categorization learned, and correction for one it learned from your own recategorizations. |
data.created_at |
string (date-time) or null | When the rule was created. |
data.updated_at |
string (date-time) or null | When the rule was last changed. |
Example request
curl -X PATCH https://whisper.money/api/v1/automation-rules/0199a3f2-6c1e-7b4d-9a8e-2f5c1d3b4a60 \
-H "Authorization: Bearer $WHISPER_MONEY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Groceries",
"priority": 10,
"conditions": {
"and": [
{
"in": [
"mercadona",
{
"var": "description"
}
]
},
{
"<": [
{
"var": "amount"
},
0
]
}
]
},
"action_label_ids": [
"0199a3f6-3c4d-7e5f-9a6b-7c8d9e0f1a23"
],
"action_note": "Weekly shop"
}'
Example response
{
"data": {
"id": "0199a3f9-5d6e-7f8a-9b0c-1d2e3f4a5b6c",
"space_id": "0199a3f2-6c1e-7b4d-9a8e-2f5c1d3b4a60",
"title": "Groceries",
"priority": 10,
"conditions": {
"and": [
{
"in": [
"mercadona",
{
"var": "description"
}
]
},
{
"<": [
{
"var": "amount"
},
0
]
}
]
},
"action_category_id": "0199a3f5-2b3c-7d4e-8f5a-6b7c8d9e0f12",
"action_label_ids": [
"0199a3f6-3c4d-7e5f-9a6b-7c8d9e0f1a23"
],
"action_note": "Weekly shop",
"origin": "user",
"created_at": "2026-01-15T09:30:00+00:00",
"updated_at": "2026-01-20T18:05:00+00:00"
}
}
Errors
| Status | When |
|---|---|
401 |
No bearer token, or one that is unknown, expired or revoked. |
403 |
The token lacks the scope (insufficient_scope), the account has no Pro plan (plan_required, with a subscribe_url) or it is a shared demo account (shared_account). |
404 |
No object with that id exists, or it belongs to someone else. |
422 |
The request failed validation. |
429 |
The rate limit is exhausted. Wait the seconds in Retry-After. |
Delete an automation rule
DELETE /api/v1/automation-rules/{automation_rule}
The rule stops running on new transactions. The transactions it already categorized or labelled keep their category and labels.
Scope: write. A personal token needs api:write (a read & write token); an OAuth token needs api:use.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
automation_rule |
path | string (uuid) | Yes | The rule's id. |
space |
query | string (uuid) | No | The id of the space to work in (see GET /spaces). Defaults to your personal space. On writes it may also be sent in the JSON body. |
Response
200
| Field | Type | Description |
|---|---|---|
id |
string (uuid) | The deleted rule's id. |
deleted |
boolean | Always true. |
Example request
curl -X DELETE https://whisper.money/api/v1/automation-rules/0199a3f2-6c1e-7b4d-9a8e-2f5c1d3b4a60 \
-H "Authorization: Bearer $WHISPER_MONEY_TOKEN"
Example response
{
"id": "0199a3f2-6c1e-7b4d-9a8e-2f5c1d3b4a60",
"deleted": true
}
Errors
| Status | When |
|---|---|
401 |
No bearer token, or one that is unknown, expired or revoked. |
403 |
The token lacks the scope (insufficient_scope), the account has no Pro plan (plan_required, with a subscribe_url) or it is a shared demo account (shared_account). |
404 |
No object with that id exists, or it belongs to someone else. |
422 |
The request failed validation. |
429 |
The rate limit is exhausted. Wait the seconds in Retry-After. |
Apply an automation rule to existing transactions
POST /api/v1/automation-rules/{automation_rule}/apply
Runs the rule over the transactions already in the space, which it otherwise never touches. By default this is a preview (dry_run: true): it answers status: preview with how many transactions match and the first 20 of them, newest first, and changes nothing. With dry_run: false it overwrites your data: every match gets the rule's category (replacing the one it had when only_uncategorized is false), its labels added and its note appended. It cannot be undone. Up to 100 matches are applied right away and answer 200 with status: done; more are applied in the background over the next few minutes and answer 202 with status: queued. There is no progress endpoint: preview again to see what the rule still matches. Previewing and applying both need a write token, and both only reach your own transactions. The matches are worked out once and reused for up to 15 minutes, so the apply that follows a preview goes over the transactions that preview reported; editing the rule starts over.
Scope: write. A personal token needs api:write (a read & write token); an OAuth token needs api:use.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
automation_rule |
path | string (uuid) | Yes | The rule's id. |
space |
query | string (uuid) | No | The id of the space to work in (see GET /spaces). Defaults to your personal space. On writes it may also be sent in the JSON body. |
Idempotency-Key |
header | string | No | Any unique string up to 255 characters. Retrying with the same key within 24 hours returns the first response instead of repeating the request. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
dry_run |
boolean | No | true (the default) only previews: it reports how many transactions the rule matches, with a sample of them, and changes nothing. Send false to apply the rule's actions to every match. |
only_uncategorized |
boolean | No | true (the default) skips the transactions that already have a category or, for a rule with labels and no category, that already carry all its labels. Send false to also take the categorized ones: the rule then overwrites the category the user or another rule gave them. Preview that combination before applying it. |
Response
200
| Field | Type | Description |
|---|---|---|
data |
RuleApplication | |
data.status |
"preview" | "done" | "queued" | preview when nothing was changed, done when the rule was applied to every match, queued when it is being applied in the background. |
data.automation_rule_id |
string (uuid) | The rule's id. |
data.total |
integer | How many transactions the rule matches. |
data.sample |
array of Transaction | On a preview, the first 20 matches, newest first; empty otherwise. |
data.sample[].id |
string (uuid) | The transaction's id. |
data.sample[].space_id |
string (uuid) or null | The id of the space the transaction is in, its account's. |
data.sample[].account |
object | The account the transaction is on: its id and name. |
data.sample[].account.id |
string | |
data.sample[].account.name |
string | |
data.sample[].transaction_date |
string (date) | The day the transaction happened. |
data.sample[].description |
string | What the transaction was for. |
data.sample[].amount |
integer | The signed amount, in the minor units of currency: negative for an expense, positive for income. |
data.sample[].currency |
string | The ISO 4217 currency the amount is in. |
data.sample[].category |
object or null | The category, if one is set: its id and name. |
data.sample[].category.id |
string | |
data.sample[].category.name |
string | |
data.sample[].category_source |
"manual" | "rule" | "ai" | "bank" | null | Who set the category: manual (you), rule (an automation rule), ai (the automatic categorization) or bank. null while there is none. |
data.sample[].labels |
array of object | The labels the transaction is tagged with: their ids and names. |
data.sample[].labels[].id |
string | |
data.sample[].labels[].name |
string | |
data.sample[].source |
"manually_created" | "imported" | "enablebanking" | "wise" | Where the transaction came from: manually_created (recorded by hand), imported (from a file), enablebanking or wise (a bank sync). Only a manually-created one can change its description, amount, currency, account or counterparty names; notes and the category can be changed on any, the date on any but one part of a split, and any but one part of a split can be deleted. |
data.sample[].creditor_name |
string or null | Who was paid, or null. |
data.sample[].debtor_name |
string or null | Who paid, or null. |
data.sample[].notes |
string or null | Free-text notes, or null. |
data.sample[].split_parent_id |
string (uuid) or null | Set when this transaction is one part of a split, otherwise null. Every part of the same split carries the same value. The split original is out of every list, and a part cannot be deleted or have its core fields changed on its own. |
data.sample[].created_at |
string (date-time) or null | When the transaction was recorded in Whisper Money. |
data.applied |
integer or null | When done, how many matches the rule went over; null otherwise. |
data.updated |
integer or null | When done, how many of them it changed: one that already had the rule's category, labels and note is applied but not updated. null otherwise. |
Example request
curl -X POST https://whisper.money/api/v1/automation-rules/0199a3f2-6c1e-7b4d-9a8e-2f5c1d3b4a60/apply \
-H "Authorization: Bearer $WHISPER_MONEY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"dry_run": true
}'
Example response
{
"data": {
"status": "preview",
"automation_rule_id": "0199a3f9-5d6e-7f8a-9b0c-1d2e3f4a5b6c",
"total": 42,
"sample": [
{
"id": "0199a3f8-4c5d-7e6f-8a9b-0c1d2e3f4a5b",
"space_id": "0199a3f2-6c1e-7b4d-9a8e-2f5c1d3b4a60",
"account": {
"id": "0199a3f4-1d2e-7c3b-8a4f-5e6d7c8b9a01",
"name": "Main checking"
},
"transaction_date": "2026-01-31",
"description": "Groceries at the market",
"amount": -4250,
"currency": "EUR",
"category": {
"id": "0199a3f5-7a8b-7c9d-8e0f-1a2b3c4d5e6f",
"name": "Groceries"
},
"category_source": "manual",
"labels": [
{
"id": "0199a3f7-3b4c-7d5e-8f6a-7b8c9d0e1f2a",
"name": "Holidays"
}
],
"source": "manually_created",
"creditor_name": "Fresh Market",
"debtor_name": null,
"notes": null,
"split_parent_id": null,
"created_at": "2026-01-31T18:12:00+00:00"
}
],
"applied": null,
"updated": null
}
}
Errors
| Status | When |
|---|---|
400 |
A malformed request: an unknown pagination cursor (invalid_cursor) or an invalid Idempotency-Key (invalid_idempotency_key). |
401 |
No bearer token, or one that is unknown, expired or revoked. |
403 |
The token lacks the scope (insufficient_scope), the account has no Pro plan (plan_required, with a subscribe_url) or it is a shared demo account (shared_account). |
404 |
No object with that id exists, or it belongs to someone else. |
409 |
A request with the same Idempotency-Key is still being processed. |
422 |
The request failed validation. |
429 |
The rate limit is exhausted. Wait the seconds in Retry-After. |