Перейти к содержимому

РАЗРАБОТЧИКАМ · API v1

Разработайте приложение для DigiMenu

Подайте заявку на доступ к API и опишите цель использования. После одобрения DigiMenu подключитесь с разрешения ресторана. В руководстве описаны заявка, установка и технические детали.

Проверено: 27 сентября 202617 операций

Как работают приложения

Для каждого приложения нужны заявка и одобрение DigiMenu. Опишите назначение приложения, зачем ему API и какие данные оно будет использовать. До одобрения установка, получение токенов и вебхуки недоступны, в том числе в режиме TEST. Подписка или доступ к кабинету разработчика не заменяют одобрение.

Приложение работает на вашем сервере. Администратор ресторана предоставляет доступ в DigiMenu. Приложение обращается к API с OAuth-токеном этой установки и получает подписанные вебхуки. Загружать код или ZIP-архивы на серверы DigiMenu не нужно.

Базовый адрес API: https://api.digimenu.us/api/v1. Приложения TEST и LIVE используют один адрес. TEST лишь ограничивает установку организацией разработчика; это не отдельная и не имитированная база данных. Используйте отдельный тестовый ресторан.

  • Можно читать меню и данные столов, получать заказы и создавать интеграции доставки.
  • В API нет методов изменения меню или товаров, создания заказов, управления складом или CRM, приёма платежей и возвратов. Не все возможности собственных приложений DigiMenu доступны сторонним разработчикам.
  • Пример работает на Node.js 22.18+ без дополнительных пакетов: подключение OAuth, чтение меню, обновление токенов и получение подписанных вебхуков.

Независимый аккаунт разработчика

Подайте заявку на developers.digimenu.us без аккаунта ресторана и подписки. Подтвердите почту, укажите сведения о себе или компании, цель приложения и нужные данные. После одобрения разработчика можно подать заявку приложения. Каждое приложение проверяется отдельно; одобрение аккаунта само по себе не даёт доступ к API.

В настройках одобренного приложения создайте изолированную тестовую среду. Она не использует таблицы клиентов и поддерживает чтение примерных меню, столов, заказов и изменение статуса доставки заказа. OAuth, курьерские процессы и вебхуки не имитируются. Ключ sandbox_ действует 24 часа и не работает на рабочем адресе /api/v1. Сброс восстанавливает тестовые данные и отменяет старый ключ.

HTTP · sandbox
GET https://api.digimenu.us/api/admin/developer-sandbox/v1/menu
Authorization: Bearer SANDBOX_TOKEN

Для рабочего использования переведите одобренное приложение в LIVE. Администратор ресторана отдельно разрешает доступ через OAuth ниже. Аккаунт разработчика не даёт вход в панель ресторана. При приостановке аккаунта блокируются также его приложения и тестовые ключи.

Регистрация и тестирование

Откройте developers.digimenu.us с одобренным независимым аккаунтом. Разработчики с аккаунтом предприятия могут продолжать использовать panel.digimenu.us/gelistirici при включённом Developer & Platform в организации. Настройки приложения ниже применимы к обоим кабинетам.

  • Создайте черновик заявки на доступ к API. Опишите назначение и необходимые данные в 40–2000 символах. Полученный clientId сам по себе не предоставляет доступ.
  • Укажите точный HTTPS-адрес перенаправления, например https://app.example/callback. Шаблоны, учётные данные и фрагменты URL не допускаются. Завершающий слеш тоже должен совпадать.
  • Для примера выберите menu:read, orders:read и webhooks:manage. Проверяйте предоставленные разрешения в каждом ответе с токенами.
  • Сохраните назначение, адреса перенаправления и разрешения, затем отправьте заявку на проверку. После одобрения DigiMenu можно создать необязательный client_secret. Если он настроен, его необходимо передавать при обмене кода и обновлении токенов. Он показывается только один раз.
  • После одобрения авторизуйте тестовый ресторан своей организации в режиме TEST. Для callback и вебхуков используйте собственный HTTPS-домен или HTTPS-туннель. HTTP-перенаправления на localhost зарегистрировать нельзя.
starter.env
APP_ORIGIN=https://eklenti.example
CLIENT_ID=YOUR_CLIENT_ID
SCOPES="menu:read orders:read webhooks:manage"
# Only if a secret was created:
# CLIENT_SECRET=YOUR_CLIENT_SECRET
# Set after registering the webhook receiver:
# WEBHOOK_SECRET=YOUR_WEBHOOK_SECRET
PORT=8787
INBOX_DIR=./webhook-inbox
Terminal
node --env-file=starter.env digimenu-starter.mjs
# HTTPS proxy/tunnel → http://127.0.0.1:8787
# Open https://eklenti.example/connect

Пример предназначен для разработки: сессии и токены хранятся в памяти, после перезапуска нужна повторная авторизация. Вебхуки записываются на локальный диск. Перед запуском добавьте вход пользователей, постоянное зашифрованное хранилище токенов, сопоставление организаций и установок, надёжную очередь задач и правила хранения данных. Не добавляйте starter.env в Git.

OAuth и PKCE

PKCE S256 обязателен для всех клиентов. При каждой попытке подключения создавайте новые code_verifier и state и привязывайте их к серверной сессии пользователя. Длина verifier — 43–128 символов. Проверяйте state до обмена кода. Код авторизации одноразовый и действует 60 секунд.

Node.js
import { randomBytes, createHash } from 'node:crypto';
const verifier = randomBytes(32).toString('base64url');
const state = randomBytes(32).toString('base64url');
const challenge = createHash('sha256').update(verifier).digest('base64url');
// Store verifier + state in this user's server session before redirecting.
const url = new URL('https://panel.digimenu.us/yetkilendir');
url.search = new URLSearchParams({
  client_id: process.env.CLIENT_ID,
  redirect_uri: 'https://eklenti.example/callback',
  scope: 'menu:read orders:read webhooks:manage',
  code_challenge: challenge,
  code_challenge_method: 'S256',
  state,
}).toString();

При согласии callback получает code и state; при отказе — error=access_denied и state. Не запрашивайте токен входа в панель управления. Получайте токены приложения через обмен ниже. Тип авторизации client_credentials не поддерживается.

HTTP
POST https://api.digimenu.us/api/v1/oauth/token
Content-Type: application/json

{
  "grant_type": "authorization_code",
  "client_id": "YOUR_CLIENT_ID",
  "code": "CODE_FROM_CALLBACK",
  "redirect_uri": "https://eklenti.example/callback",
  "code_verifier": "ORIGINAL_VERIFIER"
}
200 · JSON
{
  "access_token": "ACCESS_TOKEN",
  "refresh_token": "REFRESH_TOKEN",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "menu:read orders:read webhooks:manage"
}

Обновление токенов и удаление

Токен доступа действует 1 час, токен обновления — 60 дней. Ориентируйтесь на expires_in. При обновлении выдаётся новая пара access_token и refresh_token; сохраняйте их атомарно. Обновляйте токены каждой установки последовательно. Повторное использование старого refresh_token отзывает всё семейство токенов обновления этой установки.

HTTP
POST https://api.digimenu.us/api/v1/oauth/token
Content-Type: application/json

{
  "grant_type": "refresh_token",
  "client_id": "YOUR_CLIENT_ID",
  "refresh_token": "LATEST_REFRESH_TOKEN"
}

Если настроен client_secret, добавляйте его в запрос. Если ответ обновления потерян, не повторяйте запрос со старым токеном вслепую; подключитесь заново через OAuth. Не отправляйте токен циклически после invalid_grant.

Удаление приложения в панели закрывает доступ к API. При APP_REVOKED или APP_NOT_INSTALLED остановите синхронизацию и попросите ресторан повторно авторизовать приложение. SUBSCRIPTION_REQUIRED решается в разделе оплаты ресторана, а не обновлением токена.

Разрешения и доступ к данным

Каждый токен доступа относится к одному ресторану и одной установке. Храните разрешения и токены ресторанов отдельно, с ключами installationId и restaurantId. Разрешения не включают друг друга: orders:write не даёт orders:read.

  • menu:read — Активные категории и товары без права изменения меню.
  • orders:read — Список и детали заказов; без цен позиций, записей платежей и таблицы клиентов.
  • orders:write — Только переходы статуса на этапе доставки; без оплаты, кухни и отмены.
  • tables:read — ID, название и номер активного стола; без QR-ключей и данных о занятости.
  • deliveries:read / deliveries:write — Чтение и выполнение назначенных курьерских рейсов. Разрешение write создаёт курьера для установки.
  • customers:read — Не открывает метод /customers. Подробный адрес заказа доступен только при наличии этого разрешения И назначении заказа курьеру приложения.
  • webhooks:manage — Управление получателями и журналами доставки вебхуков приложения. Для получения событий также нужно orders:read или deliveries:read.

Запросы, страницы и повторы

cURL
curl 'https://api.digimenu.us/api/v1/orders?channel=DELIVERY&limit=25' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Accept: application/json'

Списки заказов и доставок вебхуков по умолчанию используют limit=25, допустимо 1–100. Передавайте nextCursor как cursor следующего запроса; при null остановитесь. /tables и /webhooks возвращают массивы напрямую. /menu возвращает restaurant/categories без обёртки data.

Даты используют ISO 8601. price в меню указан в основных единицах валюты (149.90), deliveryFeeMinor — в минимальных (14990). Валюта в этих ответах отсутствует; определите валюту ресторана отдельно. null может означать отсутствие данных или неприменимость поля.

Idempotency-Key действует только для /orders/{id}/transitions: это отдельный для установки кэш ответов в памяти процесса на пять минут. Используйте разные ключи для каждой комбинации заказа, операции и тела запроса. Кэш не сохраняется после перезапуска и не гарантирует защиту от повторов для всех POST-запросов. После неоднозначного сетевого сбоя проверяйте состояние перед повтором других операций записи.

Настройка и проверка вебхуков

Получатели принадлежат приложению, а не ресторану; не создавайте нового получателя для каждой установки. Нужен публичный HTTPS-адрес на порту 443. Локальные и частные адреса, а также перенаправления отклоняются. Проверяйте подпись исходных байтов запроса до разбора JSON.

HTTP
POST https://api.digimenu.us/api/v1/webhooks
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json

{
  "url": "https://eklenti.example/webhooks",
  "events": ["order.created", "order.paid"]
}

Ответ 201 показывает secret только один раз. Сохраните его безопасно. Создание получателя не идемпотентно: если ответ потерян, сначала проверьте GET /webhooks. При потере ключа отключите старого получателя и создайте нового.

Headers
X-Digimenu-Signature: t=1790467200,v1=<64-character-hex-hmac>
X-Digimenu-Event-Id: <event-uuid>
X-Digimenu-Event-Type: order.created

HMAC-SHA256(secret, timestamp + "." + rawBody)
JSON · example
{
  "id": "00000000-0000-4000-8000-000000000001",
  "type": "order.created",
  "createdAt": "2026-09-27T00:00:00.000Z",
  "restaurantId": "restaurant_example",
  "installationId": "installation_example",
  "data": { "orderId": "order_example", "channel": "TAKEAWAY" }
}

Сравнивайте подписи за постоянное время и отклоняйте метки времени с отклонением более ±300 секунд. id подписанного тела должен совпадать с X-Digimenu-Event-Id. Постоянно храните этот ID для исключения дублей и сверяйте restaurantId/installationId со своими записями установок.

Сначала надёжно сохраните событие, затем верните 2xx в течение 10 секунд. Всего выполняется до 6 попыток доставки, с задержками 30, 120, 600, 1800 и 7200 секунд перед повторами. Работа обработчика может увеличить задержку. В общей сложности 20 записей доставки FAILED автоматически отключают получателя.

Порядок событий и доставка ровно один раз не гарантируются. Получайте текущий статус заказа через GET /orders/{id}. Проверяйте попытки в GET /webhooks/{id}/deliveries. Публичных методов повторной отправки и включения получателя нет.

Список событий

  • order.created — Создан заказ на самовывоз или доставку. data: orderId, channel. Нужно orders:read; событие не гарантировано для всех сценариев заказа за столом.
  • order.paid — Завершена оплата заказа канала. data: orderId. Нужно orders:read.
  • delivery.ready — Заказ назначен внешней курьерской сети. data: orderId, runId и детали доставки. Нужно deliveries:read. Проверяйте назначенный рейс через API; не записывайте конфиденциальные данные доставки в журналы.
  • delivery.picked_up / delivery.delivered / delivery.failed — data: orderId, runId, status. Нужно deliveries:read.
  • delivery.assigned — Зарезервированное имя, принимаемое при регистрации. В текущей версии это событие не создаётся. Не стройте процесс в ожидании этого события.

Курьерская интеграция

Установите приложение с deliveries:read, deliveries:write и webhooks:manage. Добавьте orders:read для деталей заказа и customers:read для контактных данных назначенного заказа. После назначения доставки рестораном прочитайте рейс по runId из delivery.ready.

HTTP · sequence
GET /api/v1/deliveries/{runId}
POST /api/v1/deliveries/{runId}/depart
POST /api/v1/deliveries/{runId}/pings
{ "lat": 41.01, "lng": 28.97 }

POST /api/v1/deliveries/orders/{orderId}/delivered
{ "code": "CUSTOMER_DELIVERY_CODE" }

# Alternative when delivery fails:
POST /api/v1/deliveries/orders/{orderId}/failed
{ "reason": "CUSTOMER_ABSENT" }

Подтверждение доставки проверяет свежие координаты, близость к адресу и выбранный рестораном способ подтверждения. CODE требует код клиента. PHOTO/SIGNATURE требуют запись загрузки, созданную DigiMenu, но в публичной v1 нет метода загрузки подтверждения. Эти режимы нельзя полностью реализовать только через v1.

Курьерским приложениям следует использовать /deliveries. Общий метод /orders/{id}/transitions не проверяет GPS и подтверждение доставки. pings определяет активный рейс по авторизованному курьеру; runId нельзя использовать для выбора другого рейса.

Встроенные экраны

В кабинете разработчика есть embeddedUrl и embeddedOrigin. Экран работает в iframe с sandbox; не рассчитывайте на cookies, доступ к сессии или DOM родительской страницы. Токены не передаются сообщениями iframe. Начните с отдельного HTTPS-приложения.

Мост встроенных экранов ещё не является стабильным контрактом интеграции. Текущие настройки sandbox iframe и обмен сообщениями с указанием origin нужно проверять совместно от начала до конца. Не предполагайте, что придут restaurantId/locale/theme или сообщения автоматической высоты. Перед запуском проверьте этот процесс с поддержкой.

Ошибки и ограничения

Для установки действуют лимиты 30 запросов за 10 секунд и 5000 за часовое окно UTC. Общий лимит на IP — 600 в минуту, для метода токенов — 30 в минуту на IP. После 429 увеличивайте паузу со случайной задержкой. Заголовок Retry-After присутствует не всегда.

API · 403
{ "code": "insufficient_scope", "requiredScope": "orders:read", "message": "..." }
OAuth · 400
{ "error": "invalid_grant", "error_description": "..." }
  • 400 — Проверьте типы, допустимые статусы и обязательные поля. Неизвестные поля тела отклоняются. Ошибки проверки также могут иметь формат statusCode/message/error.
  • 401 — При APP_UNAUTHENTICATED обновите истёкший токен. APP_REVOKED / APP_NOT_INSTALLED требуют повторной авторизации. Для OAuth invalid_client проверьте client_id и настроенный client_secret.
  • 403 — insufficient_scope, SUBSCRIPTION_REQUIRED или ограничение курьера/подтверждения. Повторные запросы не исправляют отсутствие разрешения.
  • 404 — Ресурс отсутствует или недоступен ресторану/курьеру этого токена.
  • 409 — INVALID_TRANSITION: прочитайте текущий статус заказа перед выбором следующего перехода.
  • 429 — rate_limited / quota_exceeded или общий лимит. Замедлите очередь; при исчерпании часовой квоты дождитесь следующего часового окна UTC.
  • 5xx или сетевая ошибка — Ограничьте количество повторов чтения. Перед повтором записи проверьте её результат.

Проверка и публикация

Приложение создаётся со статусом DRAFT и режимом TEST. В DRAFT или REJECTED можно менять адреса перенаправления, разрешения и описание. Сохраните хотя бы один адрес и одно разрешение, затем отправьте на проверку IN_REVIEW. После одобрения статус станет APPROVED; затем переведите приложение в LIVE через действие публикации. Для дальнейшего изменения настроек одобренного приложения обратитесь в поддержку.

  • Проверьте согласие, отказ, неверный state и истёкший код авторизации.
  • Убедитесь, что токены и записи двух тестовых ресторанов не смешиваются.
  • Проверьте обновление токенов, потерю ответа и удаление приложения из панели.
  • Проверьте вебхуки с изменённым телом, истёкшим временем, дубликатами и нарушенным порядком.
  • Ограничьте повторы при 429 и временных ошибках; добавьте обработку повторных операций записи.
  • Передайте поддержке назначение приложения, разрешения, шаги тестирования, HTTPS-адреса и контактные данные. Не передавайте секретные ключи и пользовательские токены.

Справочник сверен с текущей реализацией v1 27 сентября 2026 года. Перед использованием новых методов или полей проверьте актуальный OpenAPI. Допускайте неизвестные поля ответа и записывайте неизвестные типы событий, не останавливая приложение.

Справочник методов API

Откройте операцию, чтобы увидеть параметры, тело запроса, поля ответа и статусы HTTP. Описания схем на английском совпадают с OpenAPI. Примеры показывают структуру, а не реальные данные ресторана.

17 / 17 операций

GET/healthСостояние сервиса

Разрешение: Общедоступно

Успешный ответ · 200

Пример ответа
{
  "status": "ok",
  "service": "api-v1",
  "ts": "2026-09-27T00:00:00.000Z"
}
Все поля и типы ответа
JSON Schema
{
  "type": "object",
  "properties": {
    "status": {
      "type": "string",
      "enum": [
        "ok"
      ]
    },
    "service": {
      "type": "string",
      "enum": [
        "api-v1"
      ]
    },
    "ts": {
      "type": "string",
      "format": "date-time"
    }
  },
  "required": [
    "status",
    "service",
    "ts"
  ]
}

200 Success

POST/oauth/tokenОбмен кода / обновление токена

Разрешение: Общедоступно

JSON only in these examples. No client_credentials grant. PKCE S256 is mandatory, even for confidential clients. Serialize refresh operations per installation; old refresh-token reuse revokes the refresh family.

Тело запроса · application/json

JSON Schema
{
  "type": "object",
  "properties": {
    "grant_type": {
      "type": "string",
      "enum": [
        "authorization_code",
        "refresh_token"
      ]
    },
    "client_id": {
      "type": "string",
      "maxLength": 200
    },
    "client_secret": {
      "type": "string",
      "description": "Required if a client secret has been configured.",
      "maxLength": 200
    },
    "code": {
      "type": "string",
      "description": "Required for authorization_code; single use, valid for 60 seconds.",
      "maxLength": 200
    },
    "redirect_uri": {
      "type": "string",
      "description": "Required for authorization_code. Exact registered URL.",
      "maxLength": 500,
      "format": "uri"
    },
    "code_verifier": {
      "type": "string",
      "description": "Required for authorization_code. Original PKCE verifier.",
      "minLength": 43,
      "maxLength": 128
    },
    "refresh_token": {
      "type": "string",
      "description": "Required for refresh_token grant.",
      "maxLength": 200
    }
  },
  "required": [
    "grant_type",
    "client_id"
  ]
}

Успешный ответ · 200

Пример ответа
{
  "access_token": "example",
  "refresh_token": "example",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "example"
}
Все поля и типы ответа
JSON Schema
{
  "type": "object",
  "properties": {
    "access_token": {
      "type": "string"
    },
    "refresh_token": {
      "type": "string"
    },
    "token_type": {
      "type": "string",
      "enum": [
        "Bearer"
      ]
    },
    "expires_in": {
      "type": "integer",
      "example": 3600
    },
    "scope": {
      "type": "string",
      "description": "Space-separated granted permissions."
    }
  },
  "required": [
    "access_token",
    "refresh_token",
    "token_type",
    "expires_in",
    "scope"
  ]
}

200 Success400 invalid_request / invalid_grant401 invalid_client403 access_denied: app application requires DigiMenu approval, including TEST mode429 30 requests per minute per IP

GET/meСведения об установке

Разрешение: Действующий токен приложения

Успешный ответ · 200

Пример ответа
{
  "installationId": "example",
  "appId": "example",
  "restaurantId": "example",
  "scopes": [
    "menu:read"
  ],
  "mode": "TEST",
  "restaurant": {
    "slug": "example",
    "name": "example"
  }
}
Все поля и типы ответа
JSON Schema
{
  "type": "object",
  "properties": {
    "installationId": {
      "type": "string"
    },
    "appId": {
      "type": "string"
    },
    "restaurantId": {
      "type": "string"
    },
    "scopes": {
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "menu:read",
          "orders:read",
          "orders:write",
          "tables:read",
          "deliveries:read",
          "deliveries:write",
          "customers:read",
          "webhooks:manage"
        ]
      }
    },
    "mode": {
      "type": "string",
      "enum": [
        "TEST",
        "LIVE"
      ]
    },
    "restaurant": {
      "type": "object",
      "properties": {
        "slug": {
          "type": "string"
        },
        "name": {
          "type": "string"
        }
      },
      "required": [
        "slug",
        "name"
      ],
      "nullable": true
    }
  },
  "required": [
    "installationId",
    "appId",
    "restaurantId",
    "scopes",
    "mode",
    "restaurant"
  ]
}

200 Success400 Invalid request or resource state401 Missing/expired token, revoked installation, or app removed403 APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction404 Resource not found within the installation429 Rate or hourly quota exceeded

GET/menuПолучить меню

Разрешение: menu:read

No pagination. Does not expose recipe cost, inventory, variants or internal preparation data.

Успешный ответ · 200

Пример ответа
{
  "restaurant": {
    "slug": "example",
    "name": "example"
  },
  "categories": [
    {
      "id": "example",
      "name": "example",
      "order": 0,
      "products": [
        {
          "id": "example",
          "name": "example",
          "description": null,
          "price": 0,
          "isActive": true,
          "order": 0,
          "allergens": null
        }
      ]
    }
  ]
}
Все поля и типы ответа
JSON Schema
{
  "type": "object",
  "properties": {
    "restaurant": {
      "type": "object",
      "properties": {
        "slug": {
          "type": "string"
        },
        "name": {
          "type": "string"
        }
      },
      "required": [
        "slug",
        "name"
      ]
    },
    "categories": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "order": {
            "type": "integer"
          },
          "products": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "description": {
                  "type": "string",
                  "nullable": true
                },
                "price": {
                  "type": "number",
                  "description": "Major currency units, not minor units. Currency is not included in this response."
                },
                "isActive": {
                  "type": "boolean"
                },
                "order": {
                  "type": "integer"
                },
                "allergens": {
                  "type": "string",
                  "nullable": true
                }
              },
              "required": [
                "id",
                "name",
                "description",
                "price",
                "isActive",
                "order",
                "allergens"
              ]
            }
          }
        },
        "required": [
          "id",
          "name",
          "order",
          "products"
        ]
      }
    }
  },
  "required": [
    "restaurant",
    "categories"
  ]
}

200 Success400 Invalid request or resource state401 Missing/expired token, revoked installation, or app removed403 APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction404 Resource not found within the installation429 Rate or hourly quota exceeded

GET/tablesСписок столов

Разрешение: tables:read

Returns a bare array. Does not expose QR secrets, sessions or occupancy.

Успешный ответ · 200

Пример ответа
[
  {
    "id": "example",
    "name": "example",
    "tableNumber": 0
  }
]
Все поля и типы ответа
JSON Schema
{
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "id": {
        "type": "string"
      },
      "name": {
        "type": "string"
      },
      "tableNumber": {
        "type": "integer"
      }
    },
    "required": [
      "id",
      "name",
      "tableNumber"
    ]
  }
}

200 Success400 Invalid request or resource state401 Missing/expired token, revoked installation, or app removed403 APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction404 Resource not found within the installation429 Rate or hourly quota exceeded

GET/ordersСписок заказов

Разрешение: orders:read

ПараметрРасположение / типОписание
limitquery / integerPage size.
{"type":"integer","minimum":1,"maximum":100,"default":25}
cursorquery / stringPass the previous nextCursor unchanged. Stop when null.
{"type":"string","maxLength":64}
channelquery / stringOrder channel.
{"type":"string","enum":["TABLE","TAKEAWAY","DELIVERY"]}
statusquery / stringUse a known order status, e.g. OUT_FOR_DELIVERY; omit for all statuses.
{"type":"string","maxLength":40}

Успешный ответ · 200

Пример ответа
{
  "data": [
    {
      "id": "example",
      "shortId": "example",
      "channel": "TABLE",
      "status": "example",
      "createdAt": "2026-09-27T00:00:00.000Z",
      "scheduledFor": null,
      "deliveryAddress": {},
      "deliveryFeeMinor": null,
      "items": [
        {
          "name": "example",
          "quantity": 0,
          "note": null
        }
      ],
      "courierRef": null
    }
  ],
  "nextCursor": null
}
Все поля и типы ответа
JSON Schema
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "shortId": {
            "type": "string"
          },
          "channel": {
            "type": "string",
            "enum": [
              "TABLE",
              "TAKEAWAY",
              "DELIVERY"
            ]
          },
          "status": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "scheduledFor": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "deliveryAddress": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Coarse locality with contactRedacted=true by default. Exact address/contact is returned only with customers:read AND assignment to this app’s courier."
          },
          "deliveryFeeMinor": {
            "type": "integer",
            "description": "Minor currency units; currency not included.",
            "nullable": true
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "quantity": {
                  "type": "integer"
                },
                "note": {
                  "type": "string",
                  "nullable": true
                }
              },
              "required": [
                "name",
                "quantity",
                "note"
              ]
            }
          },
          "courierRef": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "id",
          "shortId",
          "channel",
          "status",
          "createdAt",
          "scheduledFor",
          "deliveryAddress",
          "deliveryFeeMinor",
          "items",
          "courierRef"
        ]
      }
    },
    "nextCursor": {
      "type": "string",
      "nullable": true
    }
  },
  "required": [
    "data",
    "nextCursor"
  ]
}

200 Success400 Invalid request or resource state401 Missing/expired token, revoked installation, or app removed403 APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction404 Resource not found within the installation429 Rate or hourly quota exceeded

GET/orders/{id}Детали заказа

Разрешение: orders:read

ПараметрРасположение / типОписание
id *path / stringResource identifier.
{"type":"string"}

Успешный ответ · 200

Пример ответа
{
  "id": "example",
  "shortId": "example",
  "channel": "TABLE",
  "status": "example",
  "createdAt": "2026-09-27T00:00:00.000Z",
  "scheduledFor": null,
  "deliveryAddress": {},
  "deliveryFeeMinor": null,
  "items": [
    {
      "name": "example",
      "quantity": 0,
      "note": null
    }
  ],
  "courierRef": null
}
Все поля и типы ответа
JSON Schema
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "shortId": {
      "type": "string"
    },
    "channel": {
      "type": "string",
      "enum": [
        "TABLE",
        "TAKEAWAY",
        "DELIVERY"
      ]
    },
    "status": {
      "type": "string"
    },
    "createdAt": {
      "type": "string",
      "format": "date-time"
    },
    "scheduledFor": {
      "type": "string",
      "format": "date-time",
      "nullable": true
    },
    "deliveryAddress": {
      "type": "object",
      "nullable": true,
      "additionalProperties": true,
      "description": "Coarse locality with contactRedacted=true by default. Exact address/contact is returned only with customers:read AND assignment to this app’s courier."
    },
    "deliveryFeeMinor": {
      "type": "integer",
      "description": "Minor currency units; currency not included.",
      "nullable": true
    },
    "items": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "quantity": {
            "type": "integer"
          },
          "note": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "name",
          "quantity",
          "note"
        ]
      }
    },
    "courierRef": {
      "type": "string",
      "nullable": true
    }
  },
  "required": [
    "id",
    "shortId",
    "channel",
    "status",
    "createdAt",
    "scheduledFor",
    "deliveryAddress",
    "deliveryFeeMinor",
    "items",
    "courierRef"
  ]
}

200 Success400 Invalid request or resource state401 Missing/expired token, revoked installation, or app removed403 APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction404 Resource not found within the installation429 Rate or hourly quota exceeded

POST/orders/{id}/transitionsИзменить этап доставки

Разрешение: orders:write

ASSIGNED_TO_COURIER → OUT_FOR_DELIVERY → DELIVERED or DELIVERY_FAILED. Same status is a no-op. This generic route does not run courier GPS/proof checks: courier apps should use /deliveries. No payment, kitchen, cancel, create-order or refund operation is exposed.

ПараметрРасположение / типОписание
id *path / stringResource identifier.
{"type":"string"}
Idempotency-Keyheader / stringOptional. Unique per installation AND operation. A response is cached for 5 minutes in one process; not durable across restarts. Never reuse for another order or body.
{"type":"string"}

Тело запроса · application/json

JSON Schema
{
  "type": "object",
  "properties": {
    "status": {
      "type": "string",
      "enum": [
        "OUT_FOR_DELIVERY",
        "DELIVERED",
        "DELIVERY_FAILED"
      ]
    }
  },
  "required": [
    "status"
  ]
}

Успешный ответ · 201

Пример ответа
{
  "id": "example",
  "shortId": "example",
  "channel": "TABLE",
  "status": "example",
  "createdAt": "2026-09-27T00:00:00.000Z",
  "scheduledFor": null,
  "deliveryAddress": {},
  "deliveryFeeMinor": null,
  "items": [
    {
      "name": "example",
      "quantity": 0,
      "note": null
    }
  ],
  "courierRef": null
}
Все поля и типы ответа
JSON Schema
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "shortId": {
      "type": "string"
    },
    "channel": {
      "type": "string",
      "enum": [
        "TABLE",
        "TAKEAWAY",
        "DELIVERY"
      ]
    },
    "status": {
      "type": "string"
    },
    "createdAt": {
      "type": "string",
      "format": "date-time"
    },
    "scheduledFor": {
      "type": "string",
      "format": "date-time",
      "nullable": true
    },
    "deliveryAddress": {
      "type": "object",
      "nullable": true,
      "additionalProperties": true,
      "description": "Coarse locality with contactRedacted=true by default. Exact address/contact is returned only with customers:read AND assignment to this app’s courier."
    },
    "deliveryFeeMinor": {
      "type": "integer",
      "description": "Minor currency units; currency not included.",
      "nullable": true
    },
    "items": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "quantity": {
            "type": "integer"
          },
          "note": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "name",
          "quantity",
          "note"
        ]
      }
    },
    "courierRef": {
      "type": "string",
      "nullable": true
    }
  },
  "required": [
    "id",
    "shortId",
    "channel",
    "status",
    "createdAt",
    "scheduledFor",
    "deliveryAddress",
    "deliveryFeeMinor",
    "items",
    "courierRef"
  ]
}

201 Success400 Invalid request or resource state401 Missing/expired token, revoked installation, or app removed403 APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction404 Resource not found within the installation409 INVALID_TRANSITION429 Rate or hourly quota exceeded

GET/webhooksСписок получателей вебхуков

Разрешение: webhooks:manage

App-wide, not restaurant-specific. Register once per app, not once per installation.

Успешный ответ · 200

Пример ответа
[
  {
    "id": "example",
    "url": "https://eklenti.example/webhooks",
    "events": [
      "order.created"
    ],
    "active": true,
    "disabledAt": null,
    "createdAt": "2026-09-27T00:00:00.000Z"
  }
]
Все поля и типы ответа
JSON Schema
{
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "id": {
        "type": "string"
      },
      "url": {
        "type": "string",
        "format": "uri"
      },
      "events": {
        "type": "array",
        "items": {
          "type": "string",
          "enum": [
            "order.created",
            "order.paid",
            "delivery.ready",
            "delivery.assigned",
            "delivery.picked_up",
            "delivery.delivered",
            "delivery.failed"
          ]
        }
      },
      "active": {
        "type": "boolean"
      },
      "disabledAt": {
        "type": "string",
        "format": "date-time",
        "nullable": true
      },
      "createdAt": {
        "type": "string",
        "format": "date-time"
      }
    },
    "required": [
      "id",
      "url",
      "events",
      "active",
      "disabledAt",
      "createdAt"
    ]
  }
}

200 Success400 Invalid request or resource state401 Missing/expired token, revoked installation, or app removed403 APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction404 Resource not found within the installation429 Rate or hourly quota exceeded

POST/webhooksСоздать получателя вебхуков

Разрешение: webhooks:manage

No idempotency-key support. Check GET /webhooks before retrying a create after a network timeout; a duplicate request creates another endpoint. Secret is returned once.

Тело запроса · application/json

JSON Schema
{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Public HTTPS URL on port 443; credentials, redirects and private hosts are rejected.",
      "format": "uri",
      "maxLength": 2048
    },
    "events": {
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "order.created",
          "order.paid",
          "delivery.ready",
          "delivery.assigned",
          "delivery.picked_up",
          "delivery.delivered",
          "delivery.failed"
        ],
        "maxLength": 64
      },
      "minItems": 1
    }
  },
  "required": [
    "url",
    "events"
  ]
}

Успешный ответ · 201

Пример ответа
{
  "id": "example",
  "url": "https://eklenti.example/webhooks",
  "events": [
    "order.created"
  ],
  "active": true,
  "disabledAt": null,
  "createdAt": "2026-09-27T00:00:00.000Z",
  "secret": "example"
}
Все поля и типы ответа
JSON Schema
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "url": {
      "type": "string",
      "format": "uri"
    },
    "events": {
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "order.created",
          "order.paid",
          "delivery.ready",
          "delivery.assigned",
          "delivery.picked_up",
          "delivery.delivered",
          "delivery.failed"
        ]
      }
    },
    "active": {
      "type": "boolean"
    },
    "disabledAt": {
      "type": "string",
      "format": "date-time",
      "nullable": true
    },
    "createdAt": {
      "type": "string",
      "format": "date-time"
    },
    "secret": {
      "type": "string",
      "description": "Signing secret; returned once at creation."
    }
  },
  "required": [
    "id",
    "url",
    "events",
    "active",
    "disabledAt",
    "createdAt",
    "secret"
  ]
}

201 Success400 Invalid request or resource state401 Missing/expired token, revoked installation, or app removed403 APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction404 Resource not found within the installation429 Rate or hourly quota exceeded

DELETE/webhooks/{id}Отключить получателя вебхуков

Разрешение: webhooks:manage

Soft disable; repeating for your already-disabled endpoint succeeds. No public re-enable endpoint: register a new endpoint and store its new secret.

ПараметрРасположение / типОписание
id *path / stringResource identifier.
{"type":"string"}

Успешный ответ · 200

Пример ответа
{
  "id": "example",
  "active": false
}
Все поля и типы ответа
JSON Schema
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "active": {
      "type": "boolean",
      "enum": [
        false
      ]
    }
  },
  "required": [
    "id",
    "active"
  ]
}

200 Success400 Invalid request or resource state401 Missing/expired token, revoked installation, or app removed403 APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction404 Resource not found within the installation429 Rate or hourly quota exceeded

GET/webhooks/{id}/deliveriesЖурнал доставки вебхуков

Разрешение: webhooks:manage

ПараметрРасположение / типОписание
id *path / stringResource identifier.
{"type":"string"}
limitquery / integerPage size.
{"type":"integer","minimum":1,"maximum":100,"default":25}
cursorquery / stringPass the previous nextCursor unchanged. Stop when null.
{"type":"string","maxLength":64}

Успешный ответ · 200

Пример ответа
{
  "data": [
    {
      "id": "example",
      "eventType": "example",
      "status": "PENDING",
      "attempts": 0,
      "responseCode": null,
      "lastError": null,
      "createdAt": "2026-09-27T00:00:00.000Z"
    }
  ],
  "nextCursor": null
}
Все поля и типы ответа
JSON Schema
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "eventType": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "DELIVERED",
              "FAILED"
            ]
          },
          "attempts": {
            "type": "integer"
          },
          "responseCode": {
            "type": "integer",
            "nullable": true
          },
          "lastError": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "eventType",
          "status",
          "attempts",
          "responseCode",
          "lastError",
          "createdAt"
        ]
      }
    },
    "nextCursor": {
      "type": "string",
      "nullable": true
    }
  },
  "required": [
    "data",
    "nextCursor"
  ]
}

200 Success400 Invalid request or resource state401 Missing/expired token, revoked installation, or app removed403 APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction404 Resource not found within the installation429 Rate or hourly quota exceeded

GET/deliveries/{runId}Курьерский рейс

Разрешение: deliveries:read

Requires a courier installation created by granting deliveries:write. Reads only that installation’s courier runs.

ПараметрРасположение / типОписание
runId *path / stringResource identifier.
{"type":"string"}

Успешный ответ · 200

Пример ответа
{
  "id": "example",
  "status": "example",
  "startedAt": null,
  "completedAt": null,
  "routeDistanceMeters": null,
  "routeDurationSeconds": null,
  "orders": [
    {
      "id": "example",
      "status": "example"
    }
  ],
  "location": {
    "lat": 0,
    "lng": 0,
    "at": "2026-09-27T00:00:00.000Z"
  }
}
Все поля и типы ответа
JSON Schema
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "status": {
      "type": "string"
    },
    "startedAt": {
      "type": "string",
      "format": "date-time",
      "nullable": true
    },
    "completedAt": {
      "type": "string",
      "format": "date-time",
      "nullable": true
    },
    "routeDistanceMeters": {
      "type": "integer",
      "nullable": true
    },
    "routeDurationSeconds": {
      "type": "integer",
      "nullable": true
    },
    "orders": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "status"
        ]
      }
    },
    "location": {
      "type": "object",
      "properties": {
        "lat": {
          "type": "number"
        },
        "lng": {
          "type": "number"
        },
        "at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "lat",
        "lng",
        "at"
      ],
      "nullable": true
    }
  },
  "required": [
    "id",
    "status",
    "startedAt",
    "completedAt",
    "routeDistanceMeters",
    "routeDurationSeconds",
    "orders",
    "location"
  ]
}

200 Success400 Invalid request or resource state401 Missing/expired token, revoked installation, or app removed403 APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction404 Resource not found within the installation429 Rate or hourly quota exceeded

POST/deliveries/{runId}/departНачать рейс

Разрешение: deliveries:write

ASSIGNED → ON_ROUTE. Moves assigned orders to OUT_FOR_DELIVERY. A second depart fails with INVALID_RUN_STATE; reconcile GET before retrying.

ПараметрРасположение / типОписание
runId *path / stringResource identifier.
{"type":"string"}

Успешный ответ · 201

Пример ответа
{
  "ok": true,
  "orders": 0
}
Все поля и типы ответа
JSON Schema
{
  "type": "object",
  "properties": {
    "ok": {
      "type": "boolean"
    },
    "orders": {
      "type": "integer"
    }
  },
  "required": [
    "ok",
    "orders"
  ]
}

201 Success400 Invalid request or resource state401 Missing/expired token, revoked installation, or app removed403 APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction404 Resource not found within the installation429 Rate or hourly quota exceeded

POST/deliveries/{runId}/pingsПередать координаты

Разрешение: deliveries:write

The implementation resolves the active run from the authenticated courier and does not use runId to select a run. Send your assigned active run ID. Pings may be dropped with stored=false / THROTTLED; do not immediately retry.

ПараметрРасположение / типОписание
runId *path / stringResource identifier.
{"type":"string"}

Тело запроса · application/json

JSON Schema
{
  "type": "object",
  "properties": {
    "lat": {
      "type": "number",
      "minimum": -90,
      "maximum": 90
    },
    "lng": {
      "type": "number",
      "minimum": -180,
      "maximum": 180
    },
    "accuracyM": {
      "type": "number"
    },
    "headingDeg": {
      "type": "number"
    },
    "speedMps": {
      "type": "number"
    },
    "recordedAt": {
      "type": "string",
      "format": "date-time"
    }
  },
  "required": [
    "lat",
    "lng"
  ]
}

Успешный ответ · 201

Пример ответа
{
  "stored": true,
  "requeried": true
}
Все поля и типы ответа
JSON Schema
{
  "oneOf": [
    {
      "type": "object",
      "properties": {
        "stored": {
          "type": "boolean",
          "enum": [
            true
          ]
        },
        "requeried": {
          "type": "boolean"
        }
      },
      "required": [
        "stored",
        "requeried"
      ]
    },
    {
      "type": "object",
      "properties": {
        "stored": {
          "type": "boolean",
          "enum": [
            false
          ]
        },
        "reason": {
          "type": "string",
          "enum": [
            "THROTTLED"
          ]
        }
      },
      "required": [
        "stored",
        "reason"
      ]
    }
  ]
}

201 Success400 Invalid request or resource state401 Missing/expired token, revoked installation, or app removed403 APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction404 Resource not found within the installation429 Rate or hourly quota exceeded

POST/deliveries/orders/{orderId}/deliveredПодтвердить доставку

Разрешение: deliveries:write

Requires assigned order OUT_FOR_DELIVERY, fresh GPS near drop-off, and restaurant-selected proof. CODE requires code; PHOTO/SIGNATURE require a platform-issued upload unavailable through public v1. Do not treat these modes as a complete external-only integration.

ПараметрРасположение / типОписание
orderId *path / stringResource identifier.
{"type":"string"}

Тело запроса · application/json

JSON Schema
{
  "type": "object",
  "properties": {
    "code": {
      "type": "string",
      "description": "Required when the restaurant uses CODE proof mode.",
      "maxLength": 16
    },
    "proofRef": {
      "type": "string",
      "description": "PHOTO/SIGNATURE require a platform-issued upload. The public v1 API has no proof-upload endpoint; do not submit an arbitrary URL.",
      "maxLength": 500
    }
  },
  "required": []
}

Успешный ответ · 201

Пример ответа
{
  "ok": true
}
Все поля и типы ответа
JSON Schema
{
  "type": "object",
  "properties": {
    "ok": {
      "type": "boolean"
    }
  },
  "required": [
    "ok"
  ]
}

201 Success400 Invalid request or resource state401 Missing/expired token, revoked installation, or app removed403 APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction404 Resource not found within the installation429 Rate or hourly quota exceeded

POST/deliveries/orders/{orderId}/failedСообщить о неудачной доставке

Разрешение: deliveries:write

Requires an assigned OUT_FOR_DELIVERY order. No general idempotency header support; reconcile order state after an ambiguous response.

ПараметрРасположение / типОписание
orderId *path / stringResource identifier.
{"type":"string"}

Тело запроса · application/json

JSON Schema
{
  "type": "object",
  "properties": {
    "reason": {
      "type": "string",
      "enum": [
        "CUSTOMER_ABSENT",
        "WRONG_ADDRESS",
        "CUSTOMER_REJECTED",
        "OTHER"
      ]
    },
    "note": {
      "type": "string",
      "description": "Accepted by validation; currently not persisted by the delivery service.",
      "maxLength": 200
    }
  },
  "required": [
    "reason"
  ]
}

Успешный ответ · 201

Пример ответа
{
  "ok": true
}
Все поля и типы ответа
JSON Schema
{
  "type": "object",
  "properties": {
    "ok": {
      "type": "boolean"
    }
  },
  "required": [
    "ok"
  ]
}

201 Success400 Invalid request or resource state401 Missing/expired token, revoked installation, or app removed403 APP_APPROVAL_REQUIRED (including TEST), missing scope, inactive subscription or delivery restriction404 Resource not found within the installation429 Rate or hourly quota exceeded

Поддержка интеграций

Укажите ID приложения, метод API и код ошибки. Не отправляйте токены и секретные ключи.

support@digimenu.us