Mystery shopper
Mystery shopper visits without an app: create visits with a personal link for a guest, review submitted questionnaires with automatic fraud flags, accept a visit into a regular audit, manage the guest pool and payouts, and order turnkey checks performed by jeCheck guests.
GETList mystery shopper visits
Visits of the company, newest first. The guest link (guest_url) is returned with mystery.manage; payouts — with mystery.payouts (logged). Turnkey visits (managed) hide the guest.
| Token scope | read |
|---|---|
| Permission |
mystery.view |
| Plan feature | mystery |
| MCP tool | mystery_visits_list · read-only |
Query parameters
page
integer
1. Minimum 1.
per_page
integer
25. Value 1–100.
status
array<string>
location_ids
array<integer>
checklist_id
integer
shopper_id
integer
wave
string
managed
boolean
true — only turnkey visits, false — only own visits.
flagged
boolean
date_from
date
date_to
date
updated_since
date-time
Responses
| Status | Description |
|---|---|
| 200 | OK — a page of results with meta |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.view, or the plan has no mystery
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl 'https://app.jecheck.io/api/ext/v1/mystery/visits?checklist_id=42' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/visits?checklist_id=42', {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
},
});
const { data, meta } = await res.json();import os, requests
res = requests.get(
"https://app.jecheck.io/api/ext/v1/mystery/visits",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
params={"checklist_id":42},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('GET', 'mystery/visits', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'query' => [
'checklist_id' => 42,
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_visits_list",
"arguments": {
"checklist_id": 42
}
}
}{
"data": [
{
"id": 2041,
"uuid": "9e8d7c6b-5a49-4382-9716-05f4e3d2c1b0",
"status": "submitted",
"managed": false,
"order_uuid": null,
"location": {
"id": 12,
"name": "Abay Ave"
},
"checklist": {
"id": 310,
"name": "Guest experience"
},
"shopper": {
"id": 55,
"name": "Madina K."
},
"wave": "November",
"window_from": "2026-11-01T09:00:00+05:00",
"window_to": "2026-11-07T21:00:00+05:00",
"score": 87.5,
"level": "warning",
"submitted_at": "2026-11-03T13:40:00+05:00",
"created_at": "2026-10-30T10:00:00+05:00",
"guest_url": "https://app.jecheck.io/mg/Ab12Cd34Ef56Gh78Ij90Kl12",
"audit_uuid": null,
"payout_status": "pending",
"payout_amount": 4500,
"updated_at": "2026-11-03T13:40:00+05:00",
"url": "https://app.jecheck.io/ui/mystery/visits/2041"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 1,
"has_more": false
}
}GETRetrieve a visit
Full questionnaire: answers with per-question results, timing, guest report, geolocation vs the location, fraud flags, AI check, files (receipt, photos, audio — private media via mystery.media.get), history. Turnkey visits are available after jeCheck approves them (409 managed_visit before).
| Token scope | read |
|---|---|
| Permission |
mystery.view |
| Plan feature | mystery |
| MCP tool | mystery_visits_get · read-only |
Path parameters
id
integer
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.view, or the plan has no mystery
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl 'https://app.jecheck.io/api/ext/v1/mystery/visits/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/visits/42', {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://app.jecheck.io/api/ext/v1/mystery/visits/42",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('GET', 'mystery/visits/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_visits_get",
"arguments": {
"id": 42
}
}
}{
"data": {
"id": 2041,
"uuid": "9e8d7c6b-5a49-4382-9716-05f4e3d2c1b0",
"status": "submitted",
"managed": false,
"order_uuid": null,
"location": {
"id": 12,
"name": "Abay Ave"
},
"checklist": {
"id": 310,
"name": "Guest experience"
},
"shopper": {
"id": 55,
"name": "Madina K."
},
"wave": "November",
"window_from": "2026-11-01T09:00:00+05:00",
"window_to": "2026-11-07T21:00:00+05:00",
"score": 87.5,
"level": "warning",
"submitted_at": "2026-11-03T13:40:00+05:00",
"created_at": "2026-10-30T10:00:00+05:00",
"guest_url": "https://app.jecheck.io/mg/Ab12Cd34Ef56Gh78Ij90Kl12",
"audit_uuid": null,
"payout_status": "pending",
"payout_amount": 4500,
"updated_at": "2026-11-03T13:40:00+05:00",
"url": "https://app.jecheck.io/ui/mystery/visits/2041",
"address": "12 Abay Ave",
"brief": "Order a cappuccino and a dessert",
"legend": "Ask about vegan options",
"settings": {
"require_receipt": true,
"require_geo": true,
"require_timing": true,
"require_staff": true,
"require_audio": false,
"require_place_photos": false,
"review_required": true,
"min_minutes": 10,
"geo_radius": 300,
"receipt_limit": 5000,
"currency": "KZT"
},
"shopper_contacts": {
"email": "[email protected]",
"phone": "+7 701 000 00 00"
},
"answers": {
"8812": {
"v": 1,
"c": "Greeted within 10 seconds"
}
},
"results": {
"8812": {
"r": 1,
"t": "Yes"
}
},
"timing": {
"arrived": "2026-11-03T13:05:00+05:00",
"left": "2026-11-03T13:31:00+05:00"
},
"report": {
"staff_name": "Aliya",
"receipt_amount": 4500,
"summary": "Friendly service, long wait for dessert"
},
"geo_start": {
"lat": 43.2389,
"lng": 76.9455,
"acc": 12
},
"geo_end": null,
"geo_ref": {
"lat": 43.2391,
"lng": 76.9452
},
"distance_m": 35,
"duration_sec": 1560,
"flags": [
{
"code": "short_visit",
"level": "warning",
"text": "The visit took less than the minimum time"
}
],
"sections_score": [
{
"id": 101,
"name": "Service",
"score": 90
}
],
"ai_check": null,
"review_note": null,
"reviewer": null,
"reviewed_at": null,
"returned_count": 0,
"audit": null,
"invited_at": "2026-10-30T10:01:00+05:00",
"opened_at": "2026-11-03T12:58:00+05:00",
"started_at": "2026-11-03T13:02:00+05:00",
"form": [
{
"id": 101,
"name": "Service",
"hint": null,
"questions": [
{
"id": 8812,
"section_id": 101,
"name": "Were you greeted?",
"hint": null,
"type": "yes_no",
"settings": null,
"weight": 1,
"can_skip": false,
"photo": false
}
]
}
],
"files": [
{
"id": 9001,
"question_id": null,
"kind": "receipt",
"url": "https://files.jecheck.io/mystery/761/receipt.jpg",
"taken_at": "2026-11-03T13:30:00+05:00",
"mime": "image/jpeg",
"name": null,
"duration": null,
"size": 182044,
"transcript": null
}
],
"events": [
{
"type": "submitted",
"at": "2026-11-03T13:40:00+05:00",
"user": null,
"note": null
}
]
}
}POSTCreate visits
Creates one visit per location for a questionnaire (checklist). Each visit gets a personal guest link (guest_url) that works without the app; with shopper_id and send_email the guest receives it by email.
| Token scope | write |
|---|---|
| Permission |
mystery.manage |
| Plan feature | mystery |
| MCP tool | mystery_visits_create |
Request body
checklist_id
integer
Required location_ids
array<integer>
Required shopper_id
integer | null
wave
string | null
brief
string | null
legend
string | null
window_from
date-time | null
window_to
date-time | null
window_from).
send_email
boolean
settings
object
require_receipt
boolean
require_geo
boolean
require_timing
boolean
require_staff
boolean
require_audio
boolean
require_place_photos
boolean
review_required
boolean
min_minutes
integer | null
geo_radius
integer | null
receipt_limit
number | null
currency
string | null
Responses
| Status | Description |
|---|---|
| 201 | Created |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.manage, is read-only, or the plan has no mystery
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/mystery/visits' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"checklist_id": 42,
"location_ids": [
12,
14
],
"shopper_id": 42,
"wave": "string"
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/visits', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"checklist_id": 42,
"location_ids": [
12,
14
],
"shopper_id": 42,
"wave": "string"
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/mystery/visits",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"checklist_id":42,"location_ids":[12,14],"shopper_id":42,"wave":"string"},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('POST', 'mystery/visits', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'checklist_id' => 42,
'location_ids' => [
12,
14,
],
'shopper_id' => 42,
'wave' => 'string',
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_visits_create",
"arguments": {
"checklist_id": 42,
"location_ids": [
12,
14
],
"shopper_id": 42,
"wave": "string"
}
}
}{
"data": [
{
"id": 2041,
"location": {
"id": 12,
"name": "Abay Ave"
},
"guest_url": "https://app.jecheck.io/mg/Ab12Cd34Ef56Gh78Ij90Kl12",
"invited": true
}
]
}PATCHUpdate a visit
Change the brief, cover story, time window or guest of an open visit. The guest cannot be changed after the visit has started.
| Token scope | write |
|---|---|
| Permission |
mystery.manage |
| Plan feature | mystery |
| MCP tool | mystery_visits_update |
Path parameters
id
integer
Required Request body
brief
string | null
legend
string | null
window_from
date-time | null
window_to
date-time | null
shopper_id
integer | null
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.manage, is read-only, or the plan has no mystery
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X PATCH 'https://app.jecheck.io/api/ext/v1/mystery/visits/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"brief": "string",
"legend": "string",
"window_from": "2026-11-03T09:00:00+05:00",
"window_to": "2026-11-03T09:00:00+05:00"
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/visits/42', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"brief": "string",
"legend": "string",
"window_from": "2026-11-03T09:00:00+05:00",
"window_to": "2026-11-03T09:00:00+05:00"
}),
});
const { data } = await res.json();import os, requests
res = requests.patch(
"https://app.jecheck.io/api/ext/v1/mystery/visits/42",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"brief":"string","legend":"string","window_from":"2026-11-03T09:00:00+05:00","window_to":"2026-11-03T09:00:00+05:00"},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('PATCH', 'mystery/visits/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'brief' => 'string',
'legend' => 'string',
'window_from' => '2026-11-03T09:00:00+05:00',
'window_to' => '2026-11-03T09:00:00+05:00',
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_visits_update",
"arguments": {
"id": 42,
"brief": "string",
"legend": "string",
"window_from": "2026-11-03T09:00:00+05:00",
"window_to": "2026-11-03T09:00:00+05:00"
}
}
}{
"data": {
"id": 2041,
"uuid": "9e8d7c6b-5a49-4382-9716-05f4e3d2c1b0",
"status": "submitted",
"managed": false,
"order_uuid": null,
"location": {
"id": 12,
"name": "Abay Ave"
},
"checklist": {
"id": 310,
"name": "Guest experience"
},
"shopper": {
"id": 55,
"name": "Madina K."
},
"wave": "November",
"window_from": "2026-11-01T09:00:00+05:00",
"window_to": "2026-11-07T21:00:00+05:00",
"score": 87.5,
"level": "warning",
"submitted_at": "2026-11-03T13:40:00+05:00",
"created_at": "2026-10-30T10:00:00+05:00",
"guest_url": "https://app.jecheck.io/mg/Ab12Cd34Ef56Gh78Ij90Kl12",
"audit_uuid": null,
"payout_status": "pending",
"payout_amount": 4500,
"updated_at": "2026-11-03T13:40:00+05:00",
"url": "https://app.jecheck.io/ui/mystery/visits/2041",
"address": "12 Abay Ave",
"brief": "Order a cappuccino and a dessert",
"legend": "Ask about vegan options",
"settings": {
"require_receipt": true,
"require_geo": true,
"require_timing": true,
"require_staff": true,
"require_audio": false,
"require_place_photos": false,
"review_required": true,
"min_minutes": 10,
"geo_radius": 300,
"receipt_limit": 5000,
"currency": "KZT"
},
"shopper_contacts": {
"email": "[email protected]",
"phone": "+7 701 000 00 00"
},
"answers": {
"8812": {
"v": 1,
"c": "Greeted within 10 seconds"
}
},
"results": {
"8812": {
"r": 1,
"t": "Yes"
}
},
"timing": {
"arrived": "2026-11-03T13:05:00+05:00",
"left": "2026-11-03T13:31:00+05:00"
},
"report": {
"staff_name": "Aliya",
"receipt_amount": 4500,
"summary": "Friendly service, long wait for dessert"
},
"geo_start": {
"lat": 43.2389,
"lng": 76.9455,
"acc": 12
},
"geo_end": null,
"geo_ref": {
"lat": 43.2391,
"lng": 76.9452
},
"distance_m": 35,
"duration_sec": 1560,
"flags": [
{
"code": "short_visit",
"level": "warning",
"text": "The visit took less than the minimum time"
}
],
"sections_score": [
{
"id": 101,
"name": "Service",
"score": 90
}
],
"ai_check": null,
"review_note": null,
"reviewer": null,
"reviewed_at": null,
"returned_count": 0,
"audit": null,
"invited_at": "2026-10-30T10:01:00+05:00",
"opened_at": "2026-11-03T12:58:00+05:00",
"started_at": "2026-11-03T13:02:00+05:00",
"form": [
{
"id": 101,
"name": "Service",
"hint": null,
"questions": [
{
"id": 8812,
"section_id": 101,
"name": "Were you greeted?",
"hint": null,
"type": "yes_no",
"settings": null,
"weight": 1,
"can_skip": false,
"photo": false
}
]
}
],
"files": [
{
"id": 9001,
"question_id": null,
"kind": "receipt",
"url": "https://files.jecheck.io/mystery/761/receipt.jpg",
"taken_at": "2026-11-03T13:30:00+05:00",
"mime": "image/jpeg",
"name": null,
"duration": null,
"size": 182044,
"transcript": null
}
],
"events": [
{
"type": "submitted",
"at": "2026-11-03T13:40:00+05:00",
"user": null,
"note": null
}
]
}
}POSTAccept a visit
Accepts a submitted questionnaire: a regular audit is created from it (reports, mailings, corrective tasks follow as for any audit). Returns the visit with audit_uuid.
| Token scope | write |
|---|---|
| Permission |
mystery.manage |
| Plan feature | mystery |
| MCP tool | mystery_visits_approve |
Path parameters
id
integer
Required Request body
note
string | null
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.manage, is read-only, or the plan has no mystery
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/mystery/visits/42/approve' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"note": "Seal on fridge #2 is torn, temperature rises to +9 °C."
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/visits/42/approve', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"note": "Seal on fridge #2 is torn, temperature rises to +9 °C."
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/mystery/visits/42/approve",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"note":"Seal on fridge #2 is torn, temperature rises to +9 °C."},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('POST', 'mystery/visits/42/approve', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'note' => 'Seal on fridge #2 is torn, temperature rises to +9 °C.',
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_visits_approve",
"arguments": {
"id": 42,
"note": "Seal on fridge #2 is torn, temperature rises to +9 °C."
}
}
}{
"data": {
"id": 2041,
"uuid": "9e8d7c6b-5a49-4382-9716-05f4e3d2c1b0",
"status": "submitted",
"managed": false,
"order_uuid": null,
"location": {
"id": 12,
"name": "Abay Ave"
},
"checklist": {
"id": 310,
"name": "Guest experience"
},
"shopper": {
"id": 55,
"name": "Madina K."
},
"wave": "November",
"window_from": "2026-11-01T09:00:00+05:00",
"window_to": "2026-11-07T21:00:00+05:00",
"score": 87.5,
"level": "warning",
"submitted_at": "2026-11-03T13:40:00+05:00",
"created_at": "2026-10-30T10:00:00+05:00",
"guest_url": "https://app.jecheck.io/mg/Ab12Cd34Ef56Gh78Ij90Kl12",
"audit_uuid": null,
"payout_status": "pending",
"payout_amount": 4500,
"updated_at": "2026-11-03T13:40:00+05:00",
"url": "https://app.jecheck.io/ui/mystery/visits/2041",
"address": "12 Abay Ave",
"brief": "Order a cappuccino and a dessert",
"legend": "Ask about vegan options",
"settings": {
"require_receipt": true,
"require_geo": true,
"require_timing": true,
"require_staff": true,
"require_audio": false,
"require_place_photos": false,
"review_required": true,
"min_minutes": 10,
"geo_radius": 300,
"receipt_limit": 5000,
"currency": "KZT"
},
"shopper_contacts": {
"email": "[email protected]",
"phone": "+7 701 000 00 00"
},
"answers": {
"8812": {
"v": 1,
"c": "Greeted within 10 seconds"
}
},
"results": {
"8812": {
"r": 1,
"t": "Yes"
}
},
"timing": {
"arrived": "2026-11-03T13:05:00+05:00",
"left": "2026-11-03T13:31:00+05:00"
},
"report": {
"staff_name": "Aliya",
"receipt_amount": 4500,
"summary": "Friendly service, long wait for dessert"
},
"geo_start": {
"lat": 43.2389,
"lng": 76.9455,
"acc": 12
},
"geo_end": null,
"geo_ref": {
"lat": 43.2391,
"lng": 76.9452
},
"distance_m": 35,
"duration_sec": 1560,
"flags": [
{
"code": "short_visit",
"level": "warning",
"text": "The visit took less than the minimum time"
}
],
"sections_score": [
{
"id": 101,
"name": "Service",
"score": 90
}
],
"ai_check": null,
"review_note": null,
"reviewer": null,
"reviewed_at": null,
"returned_count": 0,
"audit": null,
"invited_at": "2026-10-30T10:01:00+05:00",
"opened_at": "2026-11-03T12:58:00+05:00",
"started_at": "2026-11-03T13:02:00+05:00",
"form": [
{
"id": 101,
"name": "Service",
"hint": null,
"questions": [
{
"id": 8812,
"section_id": 101,
"name": "Were you greeted?",
"hint": null,
"type": "yes_no",
"settings": null,
"weight": 1,
"can_skip": false,
"photo": false
}
]
}
],
"files": [
{
"id": 9001,
"question_id": null,
"kind": "receipt",
"url": "https://files.jecheck.io/mystery/761/receipt.jpg",
"taken_at": "2026-11-03T13:30:00+05:00",
"mime": "image/jpeg",
"name": null,
"duration": null,
"size": 182044,
"transcript": null
}
],
"events": [
{
"type": "submitted",
"at": "2026-11-03T13:40:00+05:00",
"user": null,
"note": null
}
]
}
}POSTReturn a visit to the guest
Sends a submitted questionnaire back for corrections with a comment; the guest gets the link again.
| Token scope | write |
|---|---|
| Permission |
mystery.manage |
| Plan feature | mystery |
| MCP tool | mystery_visits_return |
Path parameters
id
integer
Required Request body
note
string
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.manage, is read-only, or the plan has no mystery
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/mystery/visits/42/return' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"note": "Seal on fridge #2 is torn, temperature rises to +9 °C."
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/visits/42/return', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"note": "Seal on fridge #2 is torn, temperature rises to +9 °C."
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/mystery/visits/42/return",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"note":"Seal on fridge #2 is torn, temperature rises to +9 °C."},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('POST', 'mystery/visits/42/return', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'note' => 'Seal on fridge #2 is torn, temperature rises to +9 °C.',
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_visits_return",
"arguments": {
"id": 42,
"note": "Seal on fridge #2 is torn, temperature rises to +9 °C."
}
}
}{
"data": {
"id": 2041,
"uuid": "9e8d7c6b-5a49-4382-9716-05f4e3d2c1b0",
"status": "submitted",
"managed": false,
"order_uuid": null,
"location": {
"id": 12,
"name": "Abay Ave"
},
"checklist": {
"id": 310,
"name": "Guest experience"
},
"shopper": {
"id": 55,
"name": "Madina K."
},
"wave": "November",
"window_from": "2026-11-01T09:00:00+05:00",
"window_to": "2026-11-07T21:00:00+05:00",
"score": 87.5,
"level": "warning",
"submitted_at": "2026-11-03T13:40:00+05:00",
"created_at": "2026-10-30T10:00:00+05:00",
"guest_url": "https://app.jecheck.io/mg/Ab12Cd34Ef56Gh78Ij90Kl12",
"audit_uuid": null,
"payout_status": "pending",
"payout_amount": 4500,
"updated_at": "2026-11-03T13:40:00+05:00",
"url": "https://app.jecheck.io/ui/mystery/visits/2041",
"address": "12 Abay Ave",
"brief": "Order a cappuccino and a dessert",
"legend": "Ask about vegan options",
"settings": {
"require_receipt": true,
"require_geo": true,
"require_timing": true,
"require_staff": true,
"require_audio": false,
"require_place_photos": false,
"review_required": true,
"min_minutes": 10,
"geo_radius": 300,
"receipt_limit": 5000,
"currency": "KZT"
},
"shopper_contacts": {
"email": "[email protected]",
"phone": "+7 701 000 00 00"
},
"answers": {
"8812": {
"v": 1,
"c": "Greeted within 10 seconds"
}
},
"results": {
"8812": {
"r": 1,
"t": "Yes"
}
},
"timing": {
"arrived": "2026-11-03T13:05:00+05:00",
"left": "2026-11-03T13:31:00+05:00"
},
"report": {
"staff_name": "Aliya",
"receipt_amount": 4500,
"summary": "Friendly service, long wait for dessert"
},
"geo_start": {
"lat": 43.2389,
"lng": 76.9455,
"acc": 12
},
"geo_end": null,
"geo_ref": {
"lat": 43.2391,
"lng": 76.9452
},
"distance_m": 35,
"duration_sec": 1560,
"flags": [
{
"code": "short_visit",
"level": "warning",
"text": "The visit took less than the minimum time"
}
],
"sections_score": [
{
"id": 101,
"name": "Service",
"score": 90
}
],
"ai_check": null,
"review_note": null,
"reviewer": null,
"reviewed_at": null,
"returned_count": 0,
"audit": null,
"invited_at": "2026-10-30T10:01:00+05:00",
"opened_at": "2026-11-03T12:58:00+05:00",
"started_at": "2026-11-03T13:02:00+05:00",
"form": [
{
"id": 101,
"name": "Service",
"hint": null,
"questions": [
{
"id": 8812,
"section_id": 101,
"name": "Were you greeted?",
"hint": null,
"type": "yes_no",
"settings": null,
"weight": 1,
"can_skip": false,
"photo": false
}
]
}
],
"files": [
{
"id": 9001,
"question_id": null,
"kind": "receipt",
"url": "https://files.jecheck.io/mystery/761/receipt.jpg",
"taken_at": "2026-11-03T13:30:00+05:00",
"mime": "image/jpeg",
"name": null,
"duration": null,
"size": 182044,
"transcript": null
}
],
"events": [
{
"type": "submitted",
"at": "2026-11-03T13:40:00+05:00",
"user": null,
"note": null
}
]
}
}POSTReject a visit
Rejects a submitted questionnaire (e.g. fraud); no payout.
| Token scope | write |
|---|---|
| Permission |
mystery.manage |
| Plan feature | mystery |
| MCP tool | mystery_visits_reject |
Path parameters
id
integer
Required Request body
note
string
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.manage, is read-only, or the plan has no mystery
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/mystery/visits/42/reject' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"note": "Seal on fridge #2 is torn, temperature rises to +9 °C."
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/visits/42/reject', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"note": "Seal on fridge #2 is torn, temperature rises to +9 °C."
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/mystery/visits/42/reject",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"note":"Seal on fridge #2 is torn, temperature rises to +9 °C."},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('POST', 'mystery/visits/42/reject', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'note' => 'Seal on fridge #2 is torn, temperature rises to +9 °C.',
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_visits_reject",
"arguments": {
"id": 42,
"note": "Seal on fridge #2 is torn, temperature rises to +9 °C."
}
}
}{
"data": {
"id": 2041,
"uuid": "9e8d7c6b-5a49-4382-9716-05f4e3d2c1b0",
"status": "submitted",
"managed": false,
"order_uuid": null,
"location": {
"id": 12,
"name": "Abay Ave"
},
"checklist": {
"id": 310,
"name": "Guest experience"
},
"shopper": {
"id": 55,
"name": "Madina K."
},
"wave": "November",
"window_from": "2026-11-01T09:00:00+05:00",
"window_to": "2026-11-07T21:00:00+05:00",
"score": 87.5,
"level": "warning",
"submitted_at": "2026-11-03T13:40:00+05:00",
"created_at": "2026-10-30T10:00:00+05:00",
"guest_url": "https://app.jecheck.io/mg/Ab12Cd34Ef56Gh78Ij90Kl12",
"audit_uuid": null,
"payout_status": "pending",
"payout_amount": 4500,
"updated_at": "2026-11-03T13:40:00+05:00",
"url": "https://app.jecheck.io/ui/mystery/visits/2041",
"address": "12 Abay Ave",
"brief": "Order a cappuccino and a dessert",
"legend": "Ask about vegan options",
"settings": {
"require_receipt": true,
"require_geo": true,
"require_timing": true,
"require_staff": true,
"require_audio": false,
"require_place_photos": false,
"review_required": true,
"min_minutes": 10,
"geo_radius": 300,
"receipt_limit": 5000,
"currency": "KZT"
},
"shopper_contacts": {
"email": "[email protected]",
"phone": "+7 701 000 00 00"
},
"answers": {
"8812": {
"v": 1,
"c": "Greeted within 10 seconds"
}
},
"results": {
"8812": {
"r": 1,
"t": "Yes"
}
},
"timing": {
"arrived": "2026-11-03T13:05:00+05:00",
"left": "2026-11-03T13:31:00+05:00"
},
"report": {
"staff_name": "Aliya",
"receipt_amount": 4500,
"summary": "Friendly service, long wait for dessert"
},
"geo_start": {
"lat": 43.2389,
"lng": 76.9455,
"acc": 12
},
"geo_end": null,
"geo_ref": {
"lat": 43.2391,
"lng": 76.9452
},
"distance_m": 35,
"duration_sec": 1560,
"flags": [
{
"code": "short_visit",
"level": "warning",
"text": "The visit took less than the minimum time"
}
],
"sections_score": [
{
"id": 101,
"name": "Service",
"score": 90
}
],
"ai_check": null,
"review_note": null,
"reviewer": null,
"reviewed_at": null,
"returned_count": 0,
"audit": null,
"invited_at": "2026-10-30T10:01:00+05:00",
"opened_at": "2026-11-03T12:58:00+05:00",
"started_at": "2026-11-03T13:02:00+05:00",
"form": [
{
"id": 101,
"name": "Service",
"hint": null,
"questions": [
{
"id": 8812,
"section_id": 101,
"name": "Were you greeted?",
"hint": null,
"type": "yes_no",
"settings": null,
"weight": 1,
"can_skip": false,
"photo": false
}
]
}
],
"files": [
{
"id": 9001,
"question_id": null,
"kind": "receipt",
"url": "https://files.jecheck.io/mystery/761/receipt.jpg",
"taken_at": "2026-11-03T13:30:00+05:00",
"mime": "image/jpeg",
"name": null,
"duration": null,
"size": 182044,
"transcript": null
}
],
"events": [
{
"type": "submitted",
"at": "2026-11-03T13:40:00+05:00",
"user": null,
"note": null
}
]
}
}POSTCancel a visit
Cancels a visit that has not been submitted; the guest link stops working.
| Token scope | write |
|---|---|
| Permission |
mystery.manage |
| Plan feature | mystery |
| MCP tool | mystery_visits_cancel |
Path parameters
id
integer
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.manage, is read-only, or the plan has no mystery
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/mystery/visits/42/cancel' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/visits/42/cancel', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
},
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/mystery/visits/42/cancel",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('POST', 'mystery/visits/42/cancel', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_visits_cancel",
"arguments": {
"id": 42
}
}
}{
"data": {
"id": 2041,
"uuid": "9e8d7c6b-5a49-4382-9716-05f4e3d2c1b0",
"status": "submitted",
"managed": false,
"order_uuid": null,
"location": {
"id": 12,
"name": "Abay Ave"
},
"checklist": {
"id": 310,
"name": "Guest experience"
},
"shopper": {
"id": 55,
"name": "Madina K."
},
"wave": "November",
"window_from": "2026-11-01T09:00:00+05:00",
"window_to": "2026-11-07T21:00:00+05:00",
"score": 87.5,
"level": "warning",
"submitted_at": "2026-11-03T13:40:00+05:00",
"created_at": "2026-10-30T10:00:00+05:00",
"guest_url": "https://app.jecheck.io/mg/Ab12Cd34Ef56Gh78Ij90Kl12",
"audit_uuid": null,
"payout_status": "pending",
"payout_amount": 4500,
"updated_at": "2026-11-03T13:40:00+05:00",
"url": "https://app.jecheck.io/ui/mystery/visits/2041",
"address": "12 Abay Ave",
"brief": "Order a cappuccino and a dessert",
"legend": "Ask about vegan options",
"settings": {
"require_receipt": true,
"require_geo": true,
"require_timing": true,
"require_staff": true,
"require_audio": false,
"require_place_photos": false,
"review_required": true,
"min_minutes": 10,
"geo_radius": 300,
"receipt_limit": 5000,
"currency": "KZT"
},
"shopper_contacts": {
"email": "[email protected]",
"phone": "+7 701 000 00 00"
},
"answers": {
"8812": {
"v": 1,
"c": "Greeted within 10 seconds"
}
},
"results": {
"8812": {
"r": 1,
"t": "Yes"
}
},
"timing": {
"arrived": "2026-11-03T13:05:00+05:00",
"left": "2026-11-03T13:31:00+05:00"
},
"report": {
"staff_name": "Aliya",
"receipt_amount": 4500,
"summary": "Friendly service, long wait for dessert"
},
"geo_start": {
"lat": 43.2389,
"lng": 76.9455,
"acc": 12
},
"geo_end": null,
"geo_ref": {
"lat": 43.2391,
"lng": 76.9452
},
"distance_m": 35,
"duration_sec": 1560,
"flags": [
{
"code": "short_visit",
"level": "warning",
"text": "The visit took less than the minimum time"
}
],
"sections_score": [
{
"id": 101,
"name": "Service",
"score": 90
}
],
"ai_check": null,
"review_note": null,
"reviewer": null,
"reviewed_at": null,
"returned_count": 0,
"audit": null,
"invited_at": "2026-10-30T10:01:00+05:00",
"opened_at": "2026-11-03T12:58:00+05:00",
"started_at": "2026-11-03T13:02:00+05:00",
"form": [
{
"id": 101,
"name": "Service",
"hint": null,
"questions": [
{
"id": 8812,
"section_id": 101,
"name": "Were you greeted?",
"hint": null,
"type": "yes_no",
"settings": null,
"weight": 1,
"can_skip": false,
"photo": false
}
]
}
],
"files": [
{
"id": 9001,
"question_id": null,
"kind": "receipt",
"url": "https://files.jecheck.io/mystery/761/receipt.jpg",
"taken_at": "2026-11-03T13:30:00+05:00",
"mime": "image/jpeg",
"name": null,
"duration": null,
"size": 182044,
"transcript": null
}
],
"events": [
{
"type": "submitted",
"at": "2026-11-03T13:40:00+05:00",
"user": null,
"note": null
}
]
}
}POSTReopen a visit
Reopens a cancelled or expired visit with a new deadline.
| Token scope | write |
|---|---|
| Permission |
mystery.manage |
| Plan feature | mystery |
| MCP tool | mystery_visits_reopen |
Path parameters
id
integer
Required Request body
window_to
date-time | null
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.manage, is read-only, or the plan has no mystery
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/mystery/visits/42/reopen' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"window_to": "2026-11-03T09:00:00+05:00"
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/visits/42/reopen', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"window_to": "2026-11-03T09:00:00+05:00"
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/mystery/visits/42/reopen",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"window_to":"2026-11-03T09:00:00+05:00"},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('POST', 'mystery/visits/42/reopen', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'window_to' => '2026-11-03T09:00:00+05:00',
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_visits_reopen",
"arguments": {
"id": 42,
"window_to": "2026-11-03T09:00:00+05:00"
}
}
}{
"data": {
"id": 2041,
"uuid": "9e8d7c6b-5a49-4382-9716-05f4e3d2c1b0",
"status": "submitted",
"managed": false,
"order_uuid": null,
"location": {
"id": 12,
"name": "Abay Ave"
},
"checklist": {
"id": 310,
"name": "Guest experience"
},
"shopper": {
"id": 55,
"name": "Madina K."
},
"wave": "November",
"window_from": "2026-11-01T09:00:00+05:00",
"window_to": "2026-11-07T21:00:00+05:00",
"score": 87.5,
"level": "warning",
"submitted_at": "2026-11-03T13:40:00+05:00",
"created_at": "2026-10-30T10:00:00+05:00",
"guest_url": "https://app.jecheck.io/mg/Ab12Cd34Ef56Gh78Ij90Kl12",
"audit_uuid": null,
"payout_status": "pending",
"payout_amount": 4500,
"updated_at": "2026-11-03T13:40:00+05:00",
"url": "https://app.jecheck.io/ui/mystery/visits/2041",
"address": "12 Abay Ave",
"brief": "Order a cappuccino and a dessert",
"legend": "Ask about vegan options",
"settings": {
"require_receipt": true,
"require_geo": true,
"require_timing": true,
"require_staff": true,
"require_audio": false,
"require_place_photos": false,
"review_required": true,
"min_minutes": 10,
"geo_radius": 300,
"receipt_limit": 5000,
"currency": "KZT"
},
"shopper_contacts": {
"email": "[email protected]",
"phone": "+7 701 000 00 00"
},
"answers": {
"8812": {
"v": 1,
"c": "Greeted within 10 seconds"
}
},
"results": {
"8812": {
"r": 1,
"t": "Yes"
}
},
"timing": {
"arrived": "2026-11-03T13:05:00+05:00",
"left": "2026-11-03T13:31:00+05:00"
},
"report": {
"staff_name": "Aliya",
"receipt_amount": 4500,
"summary": "Friendly service, long wait for dessert"
},
"geo_start": {
"lat": 43.2389,
"lng": 76.9455,
"acc": 12
},
"geo_end": null,
"geo_ref": {
"lat": 43.2391,
"lng": 76.9452
},
"distance_m": 35,
"duration_sec": 1560,
"flags": [
{
"code": "short_visit",
"level": "warning",
"text": "The visit took less than the minimum time"
}
],
"sections_score": [
{
"id": 101,
"name": "Service",
"score": 90
}
],
"ai_check": null,
"review_note": null,
"reviewer": null,
"reviewed_at": null,
"returned_count": 0,
"audit": null,
"invited_at": "2026-10-30T10:01:00+05:00",
"opened_at": "2026-11-03T12:58:00+05:00",
"started_at": "2026-11-03T13:02:00+05:00",
"form": [
{
"id": 101,
"name": "Service",
"hint": null,
"questions": [
{
"id": 8812,
"section_id": 101,
"name": "Were you greeted?",
"hint": null,
"type": "yes_no",
"settings": null,
"weight": 1,
"can_skip": false,
"photo": false
}
]
}
],
"files": [
{
"id": 9001,
"question_id": null,
"kind": "receipt",
"url": "https://files.jecheck.io/mystery/761/receipt.jpg",
"taken_at": "2026-11-03T13:30:00+05:00",
"mime": "image/jpeg",
"name": null,
"duration": null,
"size": 182044,
"transcript": null
}
],
"events": [
{
"type": "submitted",
"at": "2026-11-03T13:40:00+05:00",
"user": null,
"note": null
}
]
}
}POSTSend the link to the guest
Emails the questionnaire link to the guest of the visit (requires a guest with an email).
| Token scope | write |
|---|---|
| Permission |
mystery.manage |
| Plan feature | mystery |
| MCP tool | mystery_visits_invite |
Path parameters
id
integer
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.manage, is read-only, or the plan has no mystery
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/mystery/visits/42/invite' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/visits/42/invite', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
},
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/mystery/visits/42/invite",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('POST', 'mystery/visits/42/invite', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_visits_invite",
"arguments": {
"id": 42
}
}
}{
"data": {
"id": 2041,
"uuid": "9e8d7c6b-5a49-4382-9716-05f4e3d2c1b0",
"status": "submitted",
"managed": false,
"order_uuid": null,
"location": {
"id": 12,
"name": "Abay Ave"
},
"checklist": {
"id": 310,
"name": "Guest experience"
},
"shopper": {
"id": 55,
"name": "Madina K."
},
"wave": "November",
"window_from": "2026-11-01T09:00:00+05:00",
"window_to": "2026-11-07T21:00:00+05:00",
"score": 87.5,
"level": "warning",
"submitted_at": "2026-11-03T13:40:00+05:00",
"created_at": "2026-10-30T10:00:00+05:00",
"guest_url": "https://app.jecheck.io/mg/Ab12Cd34Ef56Gh78Ij90Kl12",
"audit_uuid": null,
"payout_status": "pending",
"payout_amount": 4500,
"updated_at": "2026-11-03T13:40:00+05:00",
"url": "https://app.jecheck.io/ui/mystery/visits/2041",
"address": "12 Abay Ave",
"brief": "Order a cappuccino and a dessert",
"legend": "Ask about vegan options",
"settings": {
"require_receipt": true,
"require_geo": true,
"require_timing": true,
"require_staff": true,
"require_audio": false,
"require_place_photos": false,
"review_required": true,
"min_minutes": 10,
"geo_radius": 300,
"receipt_limit": 5000,
"currency": "KZT"
},
"shopper_contacts": {
"email": "[email protected]",
"phone": "+7 701 000 00 00"
},
"answers": {
"8812": {
"v": 1,
"c": "Greeted within 10 seconds"
}
},
"results": {
"8812": {
"r": 1,
"t": "Yes"
}
},
"timing": {
"arrived": "2026-11-03T13:05:00+05:00",
"left": "2026-11-03T13:31:00+05:00"
},
"report": {
"staff_name": "Aliya",
"receipt_amount": 4500,
"summary": "Friendly service, long wait for dessert"
},
"geo_start": {
"lat": 43.2389,
"lng": 76.9455,
"acc": 12
},
"geo_end": null,
"geo_ref": {
"lat": 43.2391,
"lng": 76.9452
},
"distance_m": 35,
"duration_sec": 1560,
"flags": [
{
"code": "short_visit",
"level": "warning",
"text": "The visit took less than the minimum time"
}
],
"sections_score": [
{
"id": 101,
"name": "Service",
"score": 90
}
],
"ai_check": null,
"review_note": null,
"reviewer": null,
"reviewed_at": null,
"returned_count": 0,
"audit": null,
"invited_at": "2026-10-30T10:01:00+05:00",
"opened_at": "2026-11-03T12:58:00+05:00",
"started_at": "2026-11-03T13:02:00+05:00",
"form": [
{
"id": 101,
"name": "Service",
"hint": null,
"questions": [
{
"id": 8812,
"section_id": 101,
"name": "Were you greeted?",
"hint": null,
"type": "yes_no",
"settings": null,
"weight": 1,
"can_skip": false,
"photo": false
}
]
}
],
"files": [
{
"id": 9001,
"question_id": null,
"kind": "receipt",
"url": "https://files.jecheck.io/mystery/761/receipt.jpg",
"taken_at": "2026-11-03T13:30:00+05:00",
"mime": "image/jpeg",
"name": null,
"duration": null,
"size": 182044,
"transcript": null
}
],
"events": [
{
"type": "submitted",
"at": "2026-11-03T13:40:00+05:00",
"user": null,
"note": null
}
]
}
}POSTRe-run fraud checks
Recalculates automatic flags: geolocation, time on site, receipt, photo metadata, duplicates.
| Token scope | write |
|---|---|
| Permission |
mystery.manage |
| Plan feature | mystery |
| MCP tool | mystery_visits_recheck |
Path parameters
id
integer
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.manage, is read-only, or the plan has no mystery
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/mystery/visits/42/recheck' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/visits/42/recheck', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
},
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/mystery/visits/42/recheck",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('POST', 'mystery/visits/42/recheck', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_visits_recheck",
"arguments": {
"id": 42
}
}
}{
"data": {
"id": 2041,
"uuid": "9e8d7c6b-5a49-4382-9716-05f4e3d2c1b0",
"status": "submitted",
"managed": false,
"order_uuid": null,
"location": {
"id": 12,
"name": "Abay Ave"
},
"checklist": {
"id": 310,
"name": "Guest experience"
},
"shopper": {
"id": 55,
"name": "Madina K."
},
"wave": "November",
"window_from": "2026-11-01T09:00:00+05:00",
"window_to": "2026-11-07T21:00:00+05:00",
"score": 87.5,
"level": "warning",
"submitted_at": "2026-11-03T13:40:00+05:00",
"created_at": "2026-10-30T10:00:00+05:00",
"guest_url": "https://app.jecheck.io/mg/Ab12Cd34Ef56Gh78Ij90Kl12",
"audit_uuid": null,
"payout_status": "pending",
"payout_amount": 4500,
"updated_at": "2026-11-03T13:40:00+05:00",
"url": "https://app.jecheck.io/ui/mystery/visits/2041",
"address": "12 Abay Ave",
"brief": "Order a cappuccino and a dessert",
"legend": "Ask about vegan options",
"settings": {
"require_receipt": true,
"require_geo": true,
"require_timing": true,
"require_staff": true,
"require_audio": false,
"require_place_photos": false,
"review_required": true,
"min_minutes": 10,
"geo_radius": 300,
"receipt_limit": 5000,
"currency": "KZT"
},
"shopper_contacts": {
"email": "[email protected]",
"phone": "+7 701 000 00 00"
},
"answers": {
"8812": {
"v": 1,
"c": "Greeted within 10 seconds"
}
},
"results": {
"8812": {
"r": 1,
"t": "Yes"
}
},
"timing": {
"arrived": "2026-11-03T13:05:00+05:00",
"left": "2026-11-03T13:31:00+05:00"
},
"report": {
"staff_name": "Aliya",
"receipt_amount": 4500,
"summary": "Friendly service, long wait for dessert"
},
"geo_start": {
"lat": 43.2389,
"lng": 76.9455,
"acc": 12
},
"geo_end": null,
"geo_ref": {
"lat": 43.2391,
"lng": 76.9452
},
"distance_m": 35,
"duration_sec": 1560,
"flags": [
{
"code": "short_visit",
"level": "warning",
"text": "The visit took less than the minimum time"
}
],
"sections_score": [
{
"id": 101,
"name": "Service",
"score": 90
}
],
"ai_check": null,
"review_note": null,
"reviewer": null,
"reviewed_at": null,
"returned_count": 0,
"audit": null,
"invited_at": "2026-10-30T10:01:00+05:00",
"opened_at": "2026-11-03T12:58:00+05:00",
"started_at": "2026-11-03T13:02:00+05:00",
"form": [
{
"id": 101,
"name": "Service",
"hint": null,
"questions": [
{
"id": 8812,
"section_id": 101,
"name": "Were you greeted?",
"hint": null,
"type": "yes_no",
"settings": null,
"weight": 1,
"can_skip": false,
"photo": false
}
]
}
],
"files": [
{
"id": 9001,
"question_id": null,
"kind": "receipt",
"url": "https://files.jecheck.io/mystery/761/receipt.jpg",
"taken_at": "2026-11-03T13:30:00+05:00",
"mime": "image/jpeg",
"name": null,
"duration": null,
"size": 182044,
"transcript": null
}
],
"events": [
{
"type": "submitted",
"at": "2026-11-03T13:40:00+05:00",
"user": null,
"note": null
}
]
}
}POSTRun the AI review of a visit
Transcribes audio and asks the AI to check the questionnaire for consistency (requires the AI feature for the company). The result is in ai_check of the visit.
| Token scope | write |
|---|---|
| Permission |
mystery.manage |
| Plan feature | mystery |
| MCP tool | mystery_visits_ai_review |
Path parameters
id
integer
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.manage, is read-only, or the plan has no mystery
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/mystery/visits/42/ai-review' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/visits/42/ai-review', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
},
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/mystery/visits/42/ai-review",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('POST', 'mystery/visits/42/ai-review', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_visits_ai_review",
"arguments": {
"id": 42
}
}
}{
"data": {
"id": 2041,
"uuid": "9e8d7c6b-5a49-4382-9716-05f4e3d2c1b0",
"status": "submitted",
"managed": false,
"order_uuid": null,
"location": {
"id": 12,
"name": "Abay Ave"
},
"checklist": {
"id": 310,
"name": "Guest experience"
},
"shopper": {
"id": 55,
"name": "Madina K."
},
"wave": "November",
"window_from": "2026-11-01T09:00:00+05:00",
"window_to": "2026-11-07T21:00:00+05:00",
"score": 87.5,
"level": "warning",
"submitted_at": "2026-11-03T13:40:00+05:00",
"created_at": "2026-10-30T10:00:00+05:00",
"guest_url": "https://app.jecheck.io/mg/Ab12Cd34Ef56Gh78Ij90Kl12",
"audit_uuid": null,
"payout_status": "pending",
"payout_amount": 4500,
"updated_at": "2026-11-03T13:40:00+05:00",
"url": "https://app.jecheck.io/ui/mystery/visits/2041",
"address": "12 Abay Ave",
"brief": "Order a cappuccino and a dessert",
"legend": "Ask about vegan options",
"settings": {
"require_receipt": true,
"require_geo": true,
"require_timing": true,
"require_staff": true,
"require_audio": false,
"require_place_photos": false,
"review_required": true,
"min_minutes": 10,
"geo_radius": 300,
"receipt_limit": 5000,
"currency": "KZT"
},
"shopper_contacts": {
"email": "[email protected]",
"phone": "+7 701 000 00 00"
},
"answers": {
"8812": {
"v": 1,
"c": "Greeted within 10 seconds"
}
},
"results": {
"8812": {
"r": 1,
"t": "Yes"
}
},
"timing": {
"arrived": "2026-11-03T13:05:00+05:00",
"left": "2026-11-03T13:31:00+05:00"
},
"report": {
"staff_name": "Aliya",
"receipt_amount": 4500,
"summary": "Friendly service, long wait for dessert"
},
"geo_start": {
"lat": 43.2389,
"lng": 76.9455,
"acc": 12
},
"geo_end": null,
"geo_ref": {
"lat": 43.2391,
"lng": 76.9452
},
"distance_m": 35,
"duration_sec": 1560,
"flags": [
{
"code": "short_visit",
"level": "warning",
"text": "The visit took less than the minimum time"
}
],
"sections_score": [
{
"id": 101,
"name": "Service",
"score": 90
}
],
"ai_check": null,
"review_note": null,
"reviewer": null,
"reviewed_at": null,
"returned_count": 0,
"audit": null,
"invited_at": "2026-10-30T10:01:00+05:00",
"opened_at": "2026-11-03T12:58:00+05:00",
"started_at": "2026-11-03T13:02:00+05:00",
"form": [
{
"id": 101,
"name": "Service",
"hint": null,
"questions": [
{
"id": 8812,
"section_id": 101,
"name": "Were you greeted?",
"hint": null,
"type": "yes_no",
"settings": null,
"weight": 1,
"can_skip": false,
"photo": false
}
]
}
],
"files": [
{
"id": 9001,
"question_id": null,
"kind": "receipt",
"url": "https://files.jecheck.io/mystery/761/receipt.jpg",
"taken_at": "2026-11-03T13:30:00+05:00",
"mime": "image/jpeg",
"name": null,
"duration": null,
"size": 182044,
"transcript": null
}
],
"events": [
{
"type": "submitted",
"at": "2026-11-03T13:40:00+05:00",
"user": null,
"note": null
}
]
}
}POSTSet the payout of a visit
Payout status and amount for the guest (receipt reimbursement and fee). Requires mystery.payouts.
| Token scope | write |
|---|---|
| Permission |
mystery.payouts |
| Plan feature | mystery |
| MCP tool | mystery_visits_payout |
Path parameters
id
integer
Required Request body
status
string
Required nonependingpaidamount
number | null
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.payouts, is read-only, or the plan has no mystery
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/mystery/visits/42/payout' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"status": "none",
"amount": 4.5
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/visits/42/payout', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"status": "none",
"amount": 4.5
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/mystery/visits/42/payout",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"status":"none","amount":4.5},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('POST', 'mystery/visits/42/payout', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'status' => 'none',
'amount' => 4.5,
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_visits_payout",
"arguments": {
"id": 42,
"status": "none",
"amount": 4.5
}
}
}{
"data": {
"id": 2041,
"uuid": "9e8d7c6b-5a49-4382-9716-05f4e3d2c1b0",
"status": "submitted",
"managed": false,
"order_uuid": null,
"location": {
"id": 12,
"name": "Abay Ave"
},
"checklist": {
"id": 310,
"name": "Guest experience"
},
"shopper": {
"id": 55,
"name": "Madina K."
},
"wave": "November",
"window_from": "2026-11-01T09:00:00+05:00",
"window_to": "2026-11-07T21:00:00+05:00",
"score": 87.5,
"level": "warning",
"submitted_at": "2026-11-03T13:40:00+05:00",
"created_at": "2026-10-30T10:00:00+05:00",
"guest_url": "https://app.jecheck.io/mg/Ab12Cd34Ef56Gh78Ij90Kl12",
"audit_uuid": null,
"payout_status": "pending",
"payout_amount": 4500,
"updated_at": "2026-11-03T13:40:00+05:00",
"url": "https://app.jecheck.io/ui/mystery/visits/2041",
"address": "12 Abay Ave",
"brief": "Order a cappuccino and a dessert",
"legend": "Ask about vegan options",
"settings": {
"require_receipt": true,
"require_geo": true,
"require_timing": true,
"require_staff": true,
"require_audio": false,
"require_place_photos": false,
"review_required": true,
"min_minutes": 10,
"geo_radius": 300,
"receipt_limit": 5000,
"currency": "KZT"
},
"shopper_contacts": {
"email": "[email protected]",
"phone": "+7 701 000 00 00"
},
"answers": {
"8812": {
"v": 1,
"c": "Greeted within 10 seconds"
}
},
"results": {
"8812": {
"r": 1,
"t": "Yes"
}
},
"timing": {
"arrived": "2026-11-03T13:05:00+05:00",
"left": "2026-11-03T13:31:00+05:00"
},
"report": {
"staff_name": "Aliya",
"receipt_amount": 4500,
"summary": "Friendly service, long wait for dessert"
},
"geo_start": {
"lat": 43.2389,
"lng": 76.9455,
"acc": 12
},
"geo_end": null,
"geo_ref": {
"lat": 43.2391,
"lng": 76.9452
},
"distance_m": 35,
"duration_sec": 1560,
"flags": [
{
"code": "short_visit",
"level": "warning",
"text": "The visit took less than the minimum time"
}
],
"sections_score": [
{
"id": 101,
"name": "Service",
"score": 90
}
],
"ai_check": null,
"review_note": null,
"reviewer": null,
"reviewed_at": null,
"returned_count": 0,
"audit": null,
"invited_at": "2026-10-30T10:01:00+05:00",
"opened_at": "2026-11-03T12:58:00+05:00",
"started_at": "2026-11-03T13:02:00+05:00",
"form": [
{
"id": 101,
"name": "Service",
"hint": null,
"questions": [
{
"id": 8812,
"section_id": 101,
"name": "Were you greeted?",
"hint": null,
"type": "yes_no",
"settings": null,
"weight": 1,
"can_skip": false,
"photo": false
}
]
}
],
"files": [
{
"id": 9001,
"question_id": null,
"kind": "receipt",
"url": "https://files.jecheck.io/mystery/761/receipt.jpg",
"taken_at": "2026-11-03T13:30:00+05:00",
"mime": "image/jpeg",
"name": null,
"duration": null,
"size": 182044,
"transcript": null
}
],
"events": [
{
"type": "submitted",
"at": "2026-11-03T13:40:00+05:00",
"user": null,
"note": null
}
]
}
}DELDelete a visit
An accepted visit has become an audit — delete the audit first.
| Token scope | write |
|---|---|
| Permission |
mystery.manage |
| Plan feature | mystery |
| MCP tool | mystery_visits_delete · destructive |
Path parameters
id
integer
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.manage, is read-only, or the plan has no mystery
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/mystery/visits/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/visits/42', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
},
});
const { data } = await res.json();import os, requests
res = requests.delete(
"https://app.jecheck.io/api/ext/v1/mystery/visits/42",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('DELETE', 'mystery/visits/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_visits_delete",
"arguments": {
"id": 42
}
}
}{
"data": {
"deleted": true
}
}GETDownload a private visit file
Audio / video recorded by the guest (REST only, not available as an MCP tool).
| Token scope | read |
|---|---|
| Permission |
mystery.view |
| Plan feature | mystery |
| MCP tool | Not available over MCP |
Path parameters
id
integer
Required files of the visit.
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.view, or the plan has no mystery
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl 'https://app.jecheck.io/api/ext/v1/mystery/media/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/media/42', {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://app.jecheck.io/api/ext/v1/mystery/media/42",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('GET', 'mystery/media/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"data": {
"file": "binary"
}
}GETGet mystery shopper scores by location
Accepted visits per location: count, average and last scores, trend of the last 8 visits.
| Token scope | read |
|---|---|
| Permission |
mystery.view |
| Plan feature | mystery |
| MCP tool | mystery_locations · read-only |
Query parameters
date_from
date
date_to
date
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.view, or the plan has no mystery
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl 'https://app.jecheck.io/api/ext/v1/mystery/locations?date_from=2026-11-01' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/locations?date_from=2026-11-01', {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://app.jecheck.io/api/ext/v1/mystery/locations",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
params={"date_from":"2026-11-01"},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('GET', 'mystery/locations', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'query' => [
'date_from' => '2026-11-01',
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_locations",
"arguments": {
"date_from": "2026-11-01"
}
}
}{
"data": [
{
"location": {
"id": 12,
"name": "Abay Ave"
},
"visits": 6,
"avg": 84.2,
"last": 87.5,
"prev": 80,
"last_at": "2026-11-03T13:40:00+05:00",
"trend": [
78,
80,
87.5
]
}
]
}GETList guests
The company's pool of mystery guests with visit statistics. Email and phone — only with mystery.payouts (logged).
| Token scope | read |
|---|---|
| Permission |
mystery.view |
| Plan feature | mystery |
| MCP tool | mystery_shoppers_list · read-only |
Query parameters
active
boolean
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.view, or the plan has no mystery
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl 'https://app.jecheck.io/api/ext/v1/mystery/shoppers?active=true' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/shoppers?active=true', {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://app.jecheck.io/api/ext/v1/mystery/shoppers",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
params={"active":True},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('GET', 'mystery/shoppers', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'query' => [
'active' => true,
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_shoppers_list",
"arguments": {
"active": true
}
}
}{
"data": [
{
"id": 55,
"name": "Madina K.",
"city": "Almaty",
"email": "[email protected]",
"phone": "+7 701 000 00 00",
"has_email": true,
"note": "Prefers weekends",
"is_active": true,
"visits": {
"total": 12,
"approved": 10,
"rejected": 1,
"active": 1,
"returned": 2
},
"last_visit_at": "2026-11-03T13:40:00+05:00"
}
]
}POSTAdd a guest
| Token scope | write |
|---|---|
| Permission |
mystery.manage |
| Plan feature | mystery |
| MCP tool | mystery_shoppers_create |
Request body
name
string
Required email
string | null
phone
string | null
city
string | null
note
string | null
is_active
boolean
Responses
| Status | Description |
|---|---|
| 201 | Created |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.manage, is read-only, or the plan has no mystery
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/mystery/shoppers' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "Replace the broken fridge seal",
"email": "[email protected]",
"phone": "+77010000000",
"city": "string"
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/shoppers', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Replace the broken fridge seal",
"email": "[email protected]",
"phone": "+77010000000",
"city": "string"
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/mystery/shoppers",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"name":"Replace the broken fridge seal","email":"[email protected]","phone":"+77010000000","city":"string"},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('POST', 'mystery/shoppers', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'name' => 'Replace the broken fridge seal',
'email' => '[email protected]',
'phone' => '+77010000000',
'city' => 'string',
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_shoppers_create",
"arguments": {
"name": "Replace the broken fridge seal",
"email": "[email protected]",
"phone": "+77010000000",
"city": "string"
}
}
}{
"data": {
"id": 55,
"name": "Madina K.",
"city": "Almaty",
"email": "[email protected]",
"phone": "+7 701 000 00 00",
"has_email": true,
"note": "Prefers weekends",
"is_active": true,
"visits": {
"total": 12,
"approved": 10,
"rejected": 1,
"active": 1,
"returned": 2
},
"last_visit_at": "2026-11-03T13:40:00+05:00"
}
}PATCHUpdate a guest
Contacts (email, phone) can be changed only with mystery.payouts.
| Token scope | write |
|---|---|
| Permission |
mystery.manage |
| Plan feature | mystery |
| MCP tool | mystery_shoppers_update |
Path parameters
id
integer
Required Request body
name
string
email
string | null
phone
string | null
city
string | null
note
string | null
is_active
boolean
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.manage, is read-only, or the plan has no mystery
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X PATCH 'https://app.jecheck.io/api/ext/v1/mystery/shoppers/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "Replace the broken fridge seal",
"email": "[email protected]",
"phone": "+77010000000",
"city": "string"
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/shoppers/42', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Replace the broken fridge seal",
"email": "[email protected]",
"phone": "+77010000000",
"city": "string"
}),
});
const { data } = await res.json();import os, requests
res = requests.patch(
"https://app.jecheck.io/api/ext/v1/mystery/shoppers/42",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"name":"Replace the broken fridge seal","email":"[email protected]","phone":"+77010000000","city":"string"},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('PATCH', 'mystery/shoppers/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'name' => 'Replace the broken fridge seal',
'email' => '[email protected]',
'phone' => '+77010000000',
'city' => 'string',
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_shoppers_update",
"arguments": {
"id": 42,
"name": "Replace the broken fridge seal",
"email": "[email protected]",
"phone": "+77010000000",
"city": "string"
}
}
}{
"data": {
"id": 55,
"name": "Madina K.",
"city": "Almaty",
"email": "[email protected]",
"phone": "+7 701 000 00 00",
"has_email": true,
"note": "Prefers weekends",
"is_active": true,
"visits": {
"total": 12,
"approved": 10,
"rejected": 1,
"active": 1,
"returned": 2
},
"last_visit_at": "2026-11-03T13:40:00+05:00"
}
}DELDelete a guest
| Token scope | write |
|---|---|
| Permission |
mystery.manage |
| Plan feature | mystery |
| MCP tool | mystery_shoppers_delete · destructive |
Path parameters
id
integer
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.manage, is read-only, or the plan has no mystery
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/mystery/shoppers/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/shoppers/42', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
},
});
const { data } = await res.json();import os, requests
res = requests.delete(
"https://app.jecheck.io/api/ext/v1/mystery/shoppers/42",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('DELETE', 'mystery/shoppers/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_shoppers_delete",
"arguments": {
"id": 42
}
}
}{
"data": {
"deleted": true
}
}GETList turnkey orders
Orders for mystery shopper checks performed by jeCheck guests, with progress of their visits. No plan feature is needed — the service is paid per order.
| Token scope | read |
|---|---|
| Permission |
mystery.orders |
| MCP tool | mystery_orders_list · read-only |
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.orders
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl 'https://app.jecheck.io/api/ext/v1/mystery/orders' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/orders', {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://app.jecheck.io/api/ext/v1/mystery/orders",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('GET', 'mystery/orders', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_orders_list",
"arguments": {}
}
}{
"data": [
{
"uuid": "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
"number": "MS-00042",
"status": "quoted",
"business_type": "cafe",
"scenarios": [
"service",
"cleanliness"
],
"goal": "Check the new menu launch",
"checklist_id": 310,
"needs_questionnaire": false,
"questionnaire_brief": null,
"visits_per_location": 2,
"period_from": "2026-11-10",
"period_to": "2026-11-30",
"time_slots": [
"weekday",
"evening"
],
"requirements": {
"audio": false,
"receipt": true,
"place_photos": false,
"staff": true,
"express": false
},
"shopper_profile": {
"gender": "any",
"age_from": 20,
"age_to": 35
},
"legend": null,
"reimbursement": 5000,
"currency": "KZT",
"quote": {
"currency": "KZT",
"visits": 6,
"lines": [
{
"key": "visit",
"qty": 6,
"unit": 9000,
"amount": 54000
}
],
"total": 84000,
"per_visit": 14000
},
"offer": null,
"total": 84000,
"contact_name": "Daniyar Omarov",
"contact_phone": "+7 701 000 00 01",
"comment": null,
"payment_status": "none",
"decline_reason": null,
"locations": [
{
"id": 77,
"department_id": 12,
"name": "Abay Ave",
"city": "Almaty",
"address": "12 Abay Ave",
"visits": 2,
"note": null
}
],
"problems": {},
"progress": {
"done": 0,
"avg": null,
"planned": 6
},
"submitted_at": "2026-11-03T10:00:00+05:00",
"confirmed_at": null,
"launched_at": null,
"completed_at": null,
"created_at": "2026-11-02T18:00:00+05:00",
"url": "https://app.jecheck.io/ui/mystery/orders/0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d"
}
]
}GETGet turnkey pricing catalog
Whether the service is available in the company's country, business types, cities and prices used by the quote.
| Token scope | read |
|---|---|
| Permission |
mystery.orders |
| MCP tool | mystery_orders_catalog · read-only |
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.orders
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl 'https://app.jecheck.io/api/ext/v1/mystery/orders/catalog' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/orders/catalog', {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://app.jecheck.io/api/ext/v1/mystery/orders/catalog",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('GET', 'mystery/orders/catalog', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_orders_catalog",
"arguments": {}
}
}{
"data": {
"availability": {
"available": true,
"country": "KZ",
"countries": [
"KZ"
]
},
"catalog": {
"currency": "KZT",
"cities": [
"Almaty"
],
"major_cities": [
"Almaty"
],
"business_types": [
{
"key": "cafe",
"reimbursement": 5000,
"tier": "standard"
}
]
}
}
}POSTCalculate a turnkey quote
Price estimate for the given order parameters without saving anything.
| Token scope | write |
|---|---|
| Permission |
mystery.orders |
| MCP tool | mystery_orders_quote |
Request body
business_type
string | null
restaurantcafebarcoffeefastfoodretailbeautyclinichotelotherscenarios
array<string>
goal
string | null
checklist_id
integer | null
needs_questionnaire
boolean
questionnaire_brief
string | null
visits_per_location
integer | null
period_from
date | null
period_to
date | null
time_slots
array<string>
requirements
object
audio
boolean
receipt
boolean
place_photos
boolean
staff
boolean
express
boolean
shopper_profile
object
gender
string | null
anyfmage_from
integer | null
age_to
integer | null
note
string | null
legend
string | null
reimbursement
number | null
locations
array<object>
department_id
integer
Required city
string | null
address
string | null
visits
integer | null
note
string | null
contact_name
string | null
contact_phone
string | null
comment
string | null
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.orders, is read-only
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/mystery/orders/quote' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"business_type": "restaurant",
"scenarios": [
"example"
],
"goal": "string",
"checklist_id": 42
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/orders/quote', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"business_type": "restaurant",
"scenarios": [
"example"
],
"goal": "string",
"checklist_id": 42
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/mystery/orders/quote",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"business_type":"restaurant","scenarios":["example"],"goal":"string","checklist_id":42},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('POST', 'mystery/orders/quote', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'business_type' => 'restaurant',
'scenarios' => [
'example',
],
'goal' => 'string',
'checklist_id' => 42,
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_orders_quote",
"arguments": {
"business_type": "restaurant",
"scenarios": [
"example"
],
"goal": "string",
"checklist_id": 42
}
}
}{
"data": {
"currency": "KZT",
"visits": 6,
"lines": [
{
"key": "visit",
"qty": 6,
"unit": 9000,
"amount": 54000
}
],
"total": 84000,
"per_visit": 14000
}
}GETRetrieve a turnkey order
Order terms, quote and offer, progress, visits (results after jeCheck approves them) and the message history.
| Token scope | read |
|---|---|
| Permission |
mystery.orders |
| MCP tool | mystery_orders_get · read-only |
Path parameters
uuid
uuid
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.orders
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl 'https://app.jecheck.io/api/ext/v1/mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b', {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://app.jecheck.io/api/ext/v1/mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('GET', 'mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_orders_get",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
}
}
}{
"data": {
"uuid": "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
"number": "MS-00042",
"status": "quoted",
"business_type": "cafe",
"scenarios": [
"service",
"cleanliness"
],
"goal": "Check the new menu launch",
"checklist_id": 310,
"needs_questionnaire": false,
"questionnaire_brief": null,
"visits_per_location": 2,
"period_from": "2026-11-10",
"period_to": "2026-11-30",
"time_slots": [
"weekday",
"evening"
],
"requirements": {
"audio": false,
"receipt": true,
"place_photos": false,
"staff": true,
"express": false
},
"shopper_profile": {
"gender": "any",
"age_from": 20,
"age_to": 35
},
"legend": null,
"reimbursement": 5000,
"currency": "KZT",
"quote": {
"currency": "KZT",
"visits": 6,
"lines": [
{
"key": "visit",
"qty": 6,
"unit": 9000,
"amount": 54000
}
],
"total": 84000,
"per_visit": 14000
},
"offer": null,
"total": 84000,
"contact_name": "Daniyar Omarov",
"contact_phone": "+7 701 000 00 01",
"comment": null,
"payment_status": "none",
"decline_reason": null,
"locations": [
{
"id": 77,
"department_id": 12,
"name": "Abay Ave",
"city": "Almaty",
"address": "12 Abay Ave",
"visits": 2,
"note": null
}
],
"problems": {},
"progress": {
"done": 0,
"avg": null,
"planned": 6
},
"submitted_at": "2026-11-03T10:00:00+05:00",
"confirmed_at": null,
"launched_at": null,
"completed_at": null,
"created_at": "2026-11-02T18:00:00+05:00",
"url": "https://app.jecheck.io/ui/mystery/orders/0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
"visits": [
{
"id": 2050,
"location": {
"id": 12,
"name": "Abay Ave"
},
"stage": "done",
"window_to": "2026-11-20T21:00:00+05:00",
"visited_at": "2026-11-18T19:10:00+05:00",
"score": 91,
"audit_uuid": "5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e"
}
],
"events": [
{
"id": 1,
"type": "message",
"side": "service",
"author": "Anna",
"body": "We have prepared the terms",
"payload": null,
"at": "2026-11-03T11:00:00+05:00"
}
]
}
}POSTCreate a turnkey order draft
Saves a draft with a quote; problems lists what is missing before submit. The service is currently available only in some countries (see the catalog).
| Token scope | write |
|---|---|
| Permission |
mystery.orders |
| MCP tool | mystery_orders_create |
Request body
business_type
string | null
restaurantcafebarcoffeefastfoodretailbeautyclinichotelotherscenarios
array<string>
goal
string | null
checklist_id
integer | null
needs_questionnaire
boolean
questionnaire_brief
string | null
visits_per_location
integer | null
period_from
date | null
period_to
date | null
time_slots
array<string>
requirements
object
audio
boolean
receipt
boolean
place_photos
boolean
staff
boolean
express
boolean
shopper_profile
object
gender
string | null
anyfmage_from
integer | null
age_to
integer | null
note
string | null
legend
string | null
reimbursement
number | null
locations
array<object>
department_id
integer
Required city
string | null
address
string | null
visits
integer | null
note
string | null
contact_name
string | null
contact_phone
string | null
comment
string | null
Responses
| Status | Description |
|---|---|
| 201 | Created |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.orders, is read-only
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/mystery/orders' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"business_type": "restaurant",
"scenarios": [
"example"
],
"goal": "string",
"checklist_id": 42
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/orders', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"business_type": "restaurant",
"scenarios": [
"example"
],
"goal": "string",
"checklist_id": 42
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/mystery/orders",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"business_type":"restaurant","scenarios":["example"],"goal":"string","checklist_id":42},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('POST', 'mystery/orders', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'business_type' => 'restaurant',
'scenarios' => [
'example',
],
'goal' => 'string',
'checklist_id' => 42,
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_orders_create",
"arguments": {
"business_type": "restaurant",
"scenarios": [
"example"
],
"goal": "string",
"checklist_id": 42
}
}
}{
"data": {
"uuid": "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
"number": "MS-00042",
"status": "quoted",
"business_type": "cafe",
"scenarios": [
"service",
"cleanliness"
],
"goal": "Check the new menu launch",
"checklist_id": 310,
"needs_questionnaire": false,
"questionnaire_brief": null,
"visits_per_location": 2,
"period_from": "2026-11-10",
"period_to": "2026-11-30",
"time_slots": [
"weekday",
"evening"
],
"requirements": {
"audio": false,
"receipt": true,
"place_photos": false,
"staff": true,
"express": false
},
"shopper_profile": {
"gender": "any",
"age_from": 20,
"age_to": 35
},
"legend": null,
"reimbursement": 5000,
"currency": "KZT",
"quote": {
"currency": "KZT",
"visits": 6,
"lines": [
{
"key": "visit",
"qty": 6,
"unit": 9000,
"amount": 54000
}
],
"total": 84000,
"per_visit": 14000
},
"offer": null,
"total": 84000,
"contact_name": "Daniyar Omarov",
"contact_phone": "+7 701 000 00 01",
"comment": null,
"payment_status": "none",
"decline_reason": null,
"locations": [
{
"id": 77,
"department_id": 12,
"name": "Abay Ave",
"city": "Almaty",
"address": "12 Abay Ave",
"visits": 2,
"note": null
}
],
"problems": {},
"progress": {
"done": 0,
"avg": null,
"planned": 6
},
"submitted_at": "2026-11-03T10:00:00+05:00",
"confirmed_at": null,
"launched_at": null,
"completed_at": null,
"created_at": "2026-11-02T18:00:00+05:00",
"url": "https://app.jecheck.io/ui/mystery/orders/0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d"
}
}PATCHUpdate a turnkey order draft
Only drafts can be edited; after submitting, changes are agreed with the manager in messages.
| Token scope | write |
|---|---|
| Permission |
mystery.orders |
| MCP tool | mystery_orders_update |
Path parameters
uuid
uuid
Required Request body
business_type
string | null
restaurantcafebarcoffeefastfoodretailbeautyclinichotelotherscenarios
array<string>
goal
string | null
checklist_id
integer | null
needs_questionnaire
boolean
questionnaire_brief
string | null
visits_per_location
integer | null
period_from
date | null
period_to
date | null
time_slots
array<string>
requirements
object
audio
boolean
receipt
boolean
place_photos
boolean
staff
boolean
express
boolean
shopper_profile
object
gender
string | null
anyfmage_from
integer | null
age_to
integer | null
note
string | null
legend
string | null
reimbursement
number | null
locations
array<object>
department_id
integer
Required city
string | null
address
string | null
visits
integer | null
note
string | null
contact_name
string | null
contact_phone
string | null
comment
string | null
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.orders, is read-only
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X PATCH 'https://app.jecheck.io/api/ext/v1/mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"business_type": "restaurant",
"scenarios": [
"example"
],
"goal": "string",
"checklist_id": 42
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"business_type": "restaurant",
"scenarios": [
"example"
],
"goal": "string",
"checklist_id": 42
}),
});
const { data } = await res.json();import os, requests
res = requests.patch(
"https://app.jecheck.io/api/ext/v1/mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"business_type":"restaurant","scenarios":["example"],"goal":"string","checklist_id":42},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('PATCH', 'mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'business_type' => 'restaurant',
'scenarios' => [
'example',
],
'goal' => 'string',
'checklist_id' => 42,
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_orders_update",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"business_type": "restaurant",
"scenarios": [
"example"
],
"goal": "string",
"checklist_id": 42
}
}
}{
"data": {
"uuid": "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
"number": "MS-00042",
"status": "quoted",
"business_type": "cafe",
"scenarios": [
"service",
"cleanliness"
],
"goal": "Check the new menu launch",
"checklist_id": 310,
"needs_questionnaire": false,
"questionnaire_brief": null,
"visits_per_location": 2,
"period_from": "2026-11-10",
"period_to": "2026-11-30",
"time_slots": [
"weekday",
"evening"
],
"requirements": {
"audio": false,
"receipt": true,
"place_photos": false,
"staff": true,
"express": false
},
"shopper_profile": {
"gender": "any",
"age_from": 20,
"age_to": 35
},
"legend": null,
"reimbursement": 5000,
"currency": "KZT",
"quote": {
"currency": "KZT",
"visits": 6,
"lines": [
{
"key": "visit",
"qty": 6,
"unit": 9000,
"amount": 54000
}
],
"total": 84000,
"per_visit": 14000
},
"offer": null,
"total": 84000,
"contact_name": "Daniyar Omarov",
"contact_phone": "+7 701 000 00 01",
"comment": null,
"payment_status": "none",
"decline_reason": null,
"locations": [
{
"id": 77,
"department_id": 12,
"name": "Abay Ave",
"city": "Almaty",
"address": "12 Abay Ave",
"visits": 2,
"note": null
}
],
"problems": {},
"progress": {
"done": 0,
"avg": null,
"planned": 6
},
"submitted_at": "2026-11-03T10:00:00+05:00",
"confirmed_at": null,
"launched_at": null,
"completed_at": null,
"created_at": "2026-11-02T18:00:00+05:00",
"url": "https://app.jecheck.io/ui/mystery/orders/0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d"
}
}POSTSubmit a turnkey order
Sends the completed draft to jeCheck managers, who reply with an offer.
| Token scope | write |
|---|---|
| Permission |
mystery.orders |
| MCP tool | mystery_orders_submit |
Path parameters
uuid
uuid
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.orders, is read-only
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/submit' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/submit', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
},
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/submit",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('POST', 'mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/submit', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_orders_submit",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
}
}
}{
"data": {
"uuid": "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
"number": "MS-00042",
"status": "quoted",
"business_type": "cafe",
"scenarios": [
"service",
"cleanliness"
],
"goal": "Check the new menu launch",
"checklist_id": 310,
"needs_questionnaire": false,
"questionnaire_brief": null,
"visits_per_location": 2,
"period_from": "2026-11-10",
"period_to": "2026-11-30",
"time_slots": [
"weekday",
"evening"
],
"requirements": {
"audio": false,
"receipt": true,
"place_photos": false,
"staff": true,
"express": false
},
"shopper_profile": {
"gender": "any",
"age_from": 20,
"age_to": 35
},
"legend": null,
"reimbursement": 5000,
"currency": "KZT",
"quote": {
"currency": "KZT",
"visits": 6,
"lines": [
{
"key": "visit",
"qty": 6,
"unit": 9000,
"amount": 54000
}
],
"total": 84000,
"per_visit": 14000
},
"offer": null,
"total": 84000,
"contact_name": "Daniyar Omarov",
"contact_phone": "+7 701 000 00 01",
"comment": null,
"payment_status": "none",
"decline_reason": null,
"locations": [
{
"id": 77,
"department_id": 12,
"name": "Abay Ave",
"city": "Almaty",
"address": "12 Abay Ave",
"visits": 2,
"note": null
}
],
"problems": {},
"progress": {
"done": 0,
"avg": null,
"planned": 6
},
"submitted_at": "2026-11-03T10:00:00+05:00",
"confirmed_at": null,
"launched_at": null,
"completed_at": null,
"created_at": "2026-11-02T18:00:00+05:00",
"url": "https://app.jecheck.io/ui/mystery/orders/0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d"
}
}POSTAccept the offer of a turnkey order
| Token scope | write |
|---|---|
| Permission |
mystery.orders |
| MCP tool | mystery_orders_accept |
Path parameters
uuid
uuid
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.orders, is read-only
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/accept' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/accept', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
},
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/accept",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('POST', 'mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/accept', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_orders_accept",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
}
}
}{
"data": {
"uuid": "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
"number": "MS-00042",
"status": "quoted",
"business_type": "cafe",
"scenarios": [
"service",
"cleanliness"
],
"goal": "Check the new menu launch",
"checklist_id": 310,
"needs_questionnaire": false,
"questionnaire_brief": null,
"visits_per_location": 2,
"period_from": "2026-11-10",
"period_to": "2026-11-30",
"time_slots": [
"weekday",
"evening"
],
"requirements": {
"audio": false,
"receipt": true,
"place_photos": false,
"staff": true,
"express": false
},
"shopper_profile": {
"gender": "any",
"age_from": 20,
"age_to": 35
},
"legend": null,
"reimbursement": 5000,
"currency": "KZT",
"quote": {
"currency": "KZT",
"visits": 6,
"lines": [
{
"key": "visit",
"qty": 6,
"unit": 9000,
"amount": 54000
}
],
"total": 84000,
"per_visit": 14000
},
"offer": null,
"total": 84000,
"contact_name": "Daniyar Omarov",
"contact_phone": "+7 701 000 00 01",
"comment": null,
"payment_status": "none",
"decline_reason": null,
"locations": [
{
"id": 77,
"department_id": 12,
"name": "Abay Ave",
"city": "Almaty",
"address": "12 Abay Ave",
"visits": 2,
"note": null
}
],
"problems": {},
"progress": {
"done": 0,
"avg": null,
"planned": 6
},
"submitted_at": "2026-11-03T10:00:00+05:00",
"confirmed_at": null,
"launched_at": null,
"completed_at": null,
"created_at": "2026-11-02T18:00:00+05:00",
"url": "https://app.jecheck.io/ui/mystery/orders/0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d"
}
}POSTCancel a turnkey order
| Token scope | write |
|---|---|
| Permission |
mystery.orders |
| MCP tool | mystery_orders_cancel |
Path parameters
uuid
uuid
Required Request body
reason
string | null
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.orders, is read-only
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/cancel' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"reason": "Seal on fridge #2 is torn, temperature rises to +9 °C."
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/cancel', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"reason": "Seal on fridge #2 is torn, temperature rises to +9 °C."
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/cancel",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"reason":"Seal on fridge #2 is torn, temperature rises to +9 °C."},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('POST', 'mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/cancel', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'reason' => 'Seal on fridge #2 is torn, temperature rises to +9 °C.',
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_orders_cancel",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"reason": "Seal on fridge #2 is torn, temperature rises to +9 °C."
}
}
}{
"data": {
"uuid": "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
"number": "MS-00042",
"status": "quoted",
"business_type": "cafe",
"scenarios": [
"service",
"cleanliness"
],
"goal": "Check the new menu launch",
"checklist_id": 310,
"needs_questionnaire": false,
"questionnaire_brief": null,
"visits_per_location": 2,
"period_from": "2026-11-10",
"period_to": "2026-11-30",
"time_slots": [
"weekday",
"evening"
],
"requirements": {
"audio": false,
"receipt": true,
"place_photos": false,
"staff": true,
"express": false
},
"shopper_profile": {
"gender": "any",
"age_from": 20,
"age_to": 35
},
"legend": null,
"reimbursement": 5000,
"currency": "KZT",
"quote": {
"currency": "KZT",
"visits": 6,
"lines": [
{
"key": "visit",
"qty": 6,
"unit": 9000,
"amount": 54000
}
],
"total": 84000,
"per_visit": 14000
},
"offer": null,
"total": 84000,
"contact_name": "Daniyar Omarov",
"contact_phone": "+7 701 000 00 01",
"comment": null,
"payment_status": "none",
"decline_reason": null,
"locations": [
{
"id": 77,
"department_id": 12,
"name": "Abay Ave",
"city": "Almaty",
"address": "12 Abay Ave",
"visits": 2,
"note": null
}
],
"problems": {},
"progress": {
"done": 0,
"avg": null,
"planned": 6
},
"submitted_at": "2026-11-03T10:00:00+05:00",
"confirmed_at": null,
"launched_at": null,
"completed_at": null,
"created_at": "2026-11-02T18:00:00+05:00",
"url": "https://app.jecheck.io/ui/mystery/orders/0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d"
}
}POSTWrite to the jeCheck manager
| Token scope | write |
|---|---|
| Permission |
mystery.orders |
| MCP tool | mystery_orders_messages_create |
Path parameters
uuid
uuid
Required Request body
body
string
Required Responses
| Status | Description |
|---|---|
| 201 | Created |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.orders, is read-only
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/messages' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"body": "string"
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/messages', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"body": "string"
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/messages",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"body":"string"},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('POST', 'mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/messages', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'body' => 'string',
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_orders_messages_create",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"body": "string"
}
}
}{
"data": {
"id": 2,
"type": "message",
"side": "client",
"author": "Daniyar Omarov",
"body": "Can we add one more location?",
"payload": null,
"at": "2026-11-03T12:00:00+05:00"
}
}DELDelete a turnkey order draft
Only drafts can be deleted; submitted orders are cancelled.
| Token scope | write |
|---|---|
| Permission |
mystery.orders |
| MCP tool | mystery_orders_delete · destructive |
Path parameters
uuid
uuid
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks mystery.orders, is read-only
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
},
});
const { data } = await res.json();import os, requests
res = requests.delete(
"https://app.jecheck.io/api/ext/v1/mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('DELETE', 'mystery/orders/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mystery_orders_delete",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
}
}
}{
"data": {
"deleted": true
}
}