For developers
Verified
In short
Section titled “In short”MitoOps has a public interface in three forms over the same normalised data layer. They differ in who asks and what they may do:
| Form | Direction | What it may do |
|---|---|---|
REST API (/api/v1) |
your program asks | read only — answers GET exclusively, no operation changes anything |
MCP (/api/mcp) |
an AI application asks | reads the same data and additionally has narrow writes behind sensitive scopes a person grants explicitly: automations:write (a disabled automation draft and a revision of a running one, which a person publishes), coupons:write and coupons:delete (a discount coupon with preview and confirmation), affiliate:write (affiliate programme management: partner account, portal texts, templates, campaigns, document policy), affiliate:approve (a decision on one named commission; payouts stay in the app), availabilities:draft (a proposed change to the availability list, which reaches the shop only when a person approves it in the app) and claims-settings:draft (a proposed change to the claims settings, written only when a person approves it in the app). Also claims-routes:draft, product-content:draft and category-content:draft: a proposed claims return route and proposed product and category texts, written when a person approves them in the app, or immediately if the client deliberately switches on autonomous writing for that area. Nothing else is created or changed over MCP |
| Outbound webhooks | MitoOps sends to you | a signed message about an event (order, payment, shipment, stock, invoice, claim) to your endpoint |
The interface currently exposes 130 MCP tools (102 read, 28 that write behind sensitive scopes: automation drafts and revisions, discount coupons, affiliate programme management and proposed changes to availability, claims settings and return shipping and to product and category texts, which a person writes by approving them in the app unless the client deliberately switches on autonomous writing for that area), 101 REST endpoints (all read-only) and 32 permission scopes, 13 of them sensitive, across 19 data areas. The numbers are derived from the application catalogue when this page is built; nobody types them.
What you can read over REST and MCP: shops, orders, products and categories, stock with movement history, invoices and credit notes, shipments and delivery statistics, traffic and channels, financial reports and sales, the customer directory and customer analytics in pseudonyms, suppliers, claims with statistics, the affiliate programme, automations, the shops’ availability lists, webhook endpoints and the account plan with its limits.
REST — read only
Section titled “REST — read only”The endpoint is /api/v1 on your application domain. Calls, parameters, response shape, periods and pagination are in the REST interface. The machine-readable contract is at /api/v1/openapi.json behind the same key; a signed-in person can open it from Settings → API & MCP too. The contract is generated from the same source as the interface, so it cannot drift.
Anything other than GET gets 405 before the server even looks at the key. This is not a temporary restriction — REST v1 has no write calls and the MCP writes were deliberately kept out of it. A proposed availability change can only be read over REST (its status); it cannot be created there.
MCP — reading and narrow writes
Section titled “MCP — reading and narrow writes”The endpoint is /api/mcp. MitoOps is a standard remote MCP server (Model Context Protocol, an open, vendor-neutral protocol); any application that supports remote MCP over HTTP with OAuth or an access key can connect. Claude.ai is a production-verified client; the exact steps are in the MCP interface.
MCP tools stand on the same capabilities as REST — it is not a second interface with its own queries. The tool list follows the scopes of the key or consent: a tool outside the scope does not exist for the application. Every tool carries annotations per protocol revision 2026-07-28 (readOnlyHint, destructiveHint, idempotentHint), so the AI application knows whether it is a read or a write.
OAuth — connecting on behalf of a person
Section titled “OAuth — connecting on behalf of a person”An AI application that supports remote MCP with OAuth does not connect with a key. You give it the /api/mcp address, it sends you to sign in to MitoOps (including the second factor) and on the consent screen you choose what it may read, which shops it covers and which writes it may make (automation drafts, coupons, affiliate programme management, commission decisions, availability change proposals). The application never sees your password.
What is handed over is decided by the signed-in person — and never more than they may see themselves. Whoever has no right to purchase prices cannot pass it on; whoever may not edit automations will not even see the automations:write scope on the consent screen. OAuth consent does not consume an access key from the plan limit, but it requires a plan with API & MCP — without it the consent screen does not open and says why.
Consent can be revoked at any time in Settings → API & MCP, and every access derived from it stops at the same moment.
Access key
Section titled “Access key”For a server calling a server, or for your own program:
- In the app open Settings → API & MCP and press New key.
- Enter a name you will recognise the key by later.
- Choose scopes, shops and interfaces (REST, MCP or both).
- Choose the validity and create the key.
The key is sent in a header; it is deliberately not accepted in the URL (URLs end up in logs and browser history):
Authorization: Bearer <your key>Permission scopes
Section titled “Permission scopes”A key or consent never sees more than it was granted. The table is derived from the application catalogue:
| Scope | Access | Sensitive | What it opens |
|---|---|---|---|
stores:read |
read | — | the list of shops with their code |
orders:read |
read | — | orders including items; address as country and city only, totals only with reports:read |
products:read |
read | — | products, categories and the sale price from the product card |
invoices:read |
read | — | invoices with items, credit notes and proforma invoices |
shipping:read |
read | — | shipments, tracking events, carriers (without credentials) and delivery statistics |
analytics:read |
read | — | traffic, channels, search results and order coverage by tracking |
search-console:read |
read | — | Google Search performance from the synchronized archive: days, queries, pages, countries and devices |
inventory:read |
read | — | stock levels and the history of stock movements |
reports:read |
read | sensitive | financial summary of a period (revenue, VAT, costs, result), revenue with comparison and by month, advertising (spend, budget, ROAS, cost of sale, CPA, MER), when orders come in, revenue sources, sales per product, performance per order, customers as pseudonyms and totals in the bulk order listing |
purchasing:read |
read | sensitive | suppliers, their offers and cost components |
claims:read |
read | — | claims and returns with links to the order, credit note and return shipment, the case timeline and sent e-mails; statistics and module processes |
automations:read |
read | — | the catalogue of triggers and actions, the list of automations, their settings, run history and draft validation |
automations:write |
write | sensitive | creating or editing a disabled automation draft and proposing a change to an enabled automation (revision); only a person in the app can enable a draft or publish a revision, the running automation does not change |
webhooks:read |
read | — | the event catalogue, endpoints without the secret and the delivery log without bodies |
account:read |
read | — | the plan, enabled features and limits with current usage |
affiliate:read |
read | — | the affiliate programme: overview, partners, campaigns, discount codes, conversions, payouts, statistics, settings, documents, public portal, e-mail templates, help articles and code requests; partner contacts only with personal-data:read, bank and tax data never |
affiliate:write |
write | sensitive | affiliate programme management: partner account decisions (approve, reject, suspend), code request handling, non-financial programme settings, portal texts, help articles, e-mail templates, campaigns and document policy; commission decisions have their own scope, payouts stay in the app |
affiliate:approve |
write | sensitive | a decision on one affiliate commission by conversion id: approve, reject or cancel (rejection and cancellation with a reason, the partner is e-mailed); a paid commission is never reverted, bulk approval and payouts do not exist externally |
customers:read |
read | — | the customer directory: pseudonym, shops, country, language, lifetime counts and dates; name, company, e-mail and phone only with personal-data:read, revenue and LTV only with reports:read |
coupons:read |
read | — | the shop’s discount coupons with discount and validity, platform support, the activation link and its readiness |
coupons:write |
write | sensitive | creating a coupon on selected shops (an existing one with different parameters is not overwritten without explicit consent) |
coupons:delete |
write | sensitive | irreversible deletion of a coupon on the selected shop after a preview and explicit confirmation; a coupon with a live dependency (AI Mailing, sign-up window, scheduled campaign, partner) is not deleted |
chatbot:read |
read | — | web chatbot statistics for a period: teaser impressions and clicks (click rate), chat opens including how they started, conversation and message counts, outcomes, customer ratings, the newsletter sign-up funnel and a deterministic breakdown of conversation topics (shares, products, knowledge-gap candidates) — totals only |
chatbot-conversations:read |
read | sensitive | customer conversations with the web chatbot: a list with the first question and transcripts with the bot’s answer sources; the customer is only a random conversation key, e-mail, phone and IBAN inside the text only with personal-data:read, otherwise replaced by a placeholder; only within the shop’s retention |
availabilities:draft |
write | sensitive | a proposed change to the shop’s availability list (create, update, delete) with a preview; it reaches the shop only when a person with the right permissions approves it in the app, otherwise it expires after 24 hours; it changes neither which availability a product has nor stock levels |
claims-settings:read |
read | — | claim e-mail and document templates, module settings, tags, return shipping and the shop form; no access tokens |
claims-settings:draft |
write | sensitive | a proposed change to claim processes, statuses, tags and template texts with a preview; it is written only when a person with the right permissions approves it in the app, otherwise it expires after 72 hours; nothing is deleted |
claims-routes:draft |
write | sensitive | a proposal to create, update, enable or disable a return route, validated like the screen; a person writes it by approving it in the app, or immediately if the client deliberately switched on autonomous writing for that area; never deletes a route |
product-content:read |
read | — | a product’s description, short description and SEO texts straight from the shop, with a hash and writability for each field |
product-content:draft |
write | sensitive | proposed new product texts (up to 30 at once), content fields only, never price, stock, code or EAN; a person writes it by approving it, or immediately when autonomous writing is deliberately switched on |
category-content:read |
read | — | a category’s top and bottom description and SEO texts, with a hash and writability depending on the shop platform |
category-content:draft |
write | sensitive | proposed new category texts (up to 30 at once), only fields the shop platform can write; a person writes it by approving it, or immediately when autonomous writing is deliberately switched on |
Sensitive scopes are not pre-selected on the key screen or on the consent screen — a person has to tick them deliberately. purchase-prices:read and personal-data:read have no tool of their own; they decide about fields in the other responses. A missing field is not zero — it is missing.
Scopes are a public commitment: they change only backwards-compatibly, and a credential issued earlier does not inherit a new scope (scopes are recorded in it by name). That is why an older key or an older consent did not receive personal data when they got a scope of their own on 2 September 2026, and will not receive the draft write either — that needs a new consent or a new key.
A new scope can also be added to an existing key without replacing the key: Settings → API & MCP → Edit scopes. The key value stays the same; the integration using it keeps running and gets the new scope from its next request. The change is made by a person allowed to manage keys; the plan and sensitive scopes are checked the same way as when issuing a key.
Personal data
Section titled “Personal data”The interface returns operational data; personal data only with the personal-data:read scope:
- Orders and claims without it return only the country and city — not the name, e-mail, phone or street.
- The customer directory (
customers:read) on its own returns only the pseudonym, shops, country, language, counts and dates. Name, company, e-mail, phone and marketing gender are added bypersonal-data:read, revenue and LTV byreports:read— a field you have no scope for is removed, not zeroed. - Customer analytics (
customers/performance) has no personal data at all: the customer is a pseudonym (a hash of the e-mail), the same ascustomerEmailHashon documents and in the directory. - Supplier and affiliate partner contacts are behind the same scope.
- Web chatbot conversations (
chatbot-conversations:read, sensitive) carry only a random conversation key — no name, e-mail, IP or cookie. An e-mail, phone or IBAN the customer typed into the text is returned only withpersonal-data:read; without it a placeholder takes its place. - Bank and tax data of partners (IBAN, company and VAT numbers, billing data of payouts), internal notes, passwords and second-factor secrets are never returned — no scope opens them.
- Webhooks send identifiers and states, not order contents or customer data.
Every call is written to the audit log without input values, only with field names and a fingerprint.
Automations: the safe draft write
Section titled “Automations: the safe draft write”An AI assistant may propose an automation, it may not enable it. With the automations:write scope (sensitive, never pre-selected, offered only to a person with the right to edit automations):
automations_create_draftcreates a draft in the disabled state — it does not touch the published version, triggers or runs;automations_update_draftedits only a draft nobody has published yet; a draft being edited in the application editor is not overwritten;- the draft appears in Automations like any other work in progress, and only a person in the app with the approval right can enable, publish or run it;
automations_revision_create_draftproposes a change to a published, even enabled automation as a revision; the running version stays unchanged until a person loads the revision in the editor and publishes it (automations_revision_update_draft,automations_revision_discard_draft).
Values of fields picked from a list in the editor (order status, shipping, payment, claim status…) come from automations_options in the shape the editor stores. A value that does not exist in the shop and placeholder text such as DOPLNIT_… are validation errors, not success.
Creation is idempotent via clientRequestId, an update requires expectedVersion, and both require the catalogVersion from automations_catalog — a stale catalogue is a conflict, not a silent write. A draft that refers to an unknown trigger, a shop outside the scope or someone else’s webhook endpoint is not saved. Details in the MCP interface.
Availability: a proposed change that a person approves
Section titled “Availability: a proposed change that a person approves”Availabilities are the entries of a specific shop’s availability list that the shop shows next to a product, for example In stock, Backorder or Preorder: a name, a description, restock and delivery time in hours, a meaning for Google Shopping and a colour. They are not stock levels.
availabilities_listandGET /availabilities?market=(scopeproducts:read) return the list of one shop;marketis required. Themanageablefield says whether that shop’s list can be changed from MitoOps, andreasonsays why not:PLATFORMA(the platform cannot do it),BEZ_ROZSIRENIA(a WooCommerce shop without the MitoOps plugin) orPROSTREDIE(writes to shops are switched off in this environment).availabilities_change_draft(MCP only, sensitive scopeavailabilities:draft) writes nothing to the shop. It validates the change, stores it as a proposal valid for 24 hours and returns a preview (each field before and after, warnings, blocking errors), thedraftIdand anapprovalUrl.- The proposal reaches the shop only when a person in the app clicks Approve and write under Warehouse → Availability → Manage, or rejects it. What counts is that person’s permissions at the moment of the click, not the scope of the key or consent. Neither a model nor an access key can write anything to the shop without a person.
availabilities_draft_getandGET /availabilities/drafts/:draftId(scopeproducts:read) return the status of the proposal:pending,writing,executed,partial,failed,rejectedorexpired.
The availabilities:draft scope is offered only to a person who could also approve the change (the rights to manage stock sync and to edit products). An existing key or consent does not inherit it. REST v1 stays read-only. The proposal parameters are in the MCP interface, the approval screen in the Availability guide.
Claims: settings for reading and a proposed change
Section titled “Claims: settings for reading and a proposed change”claims_settings(scopeclaims:read) returns the processes with IDs and names of types, steps and statuses, and the tags; with theclaims-settings:readscope also the module settings.claims_templatesandclaims_configuration(scopeclaims-settings:read) return e-mail and document templates (subject, text, when and whether they are sent automatically) and the other settings: tags, fields, return shipping and the shop form, without the integration token.claims_getalso carries the case timeline, sent e-mails and tags; message text only withpersonal-data:read.claims_config_change_draft(MCP only, sensitive scopeclaims-settings:draft) does not change the settings. It stores a proposed change to processes, statuses, tags and template texts for 72 hours with a preview andapprovalUrl; a person allowed to manage the settings writes it with Approve and write under Claims → Settings, in full or not at all.claims_config_draft_getreturns its state.
Parameters are in the MCP interface.
Return shipping, product texts and autonomous writing
Section titled “Return shipping, product texts and autonomous writing”claims_routes(scopeclaims-settings:read, or either claims drafting scope) returns return shipping routes, recipient addresses, carrier profiles with IDs, a return flag and reach, and case type keys.claims_routes_change_draft(MCP only, sensitive scopeclaims-routes:draft) proposes creating, updating, enabling or disabling a route. The server validates it exactly like the screen: a profile with returns enabled, carrier reach, an existing address and types, a non-negative price and no conflict with an enabled route. Deleting a route over MCP is not possible.products_content_getandGET /products/:code/content?market=(scopeproduct-content:read) return a product’s description, short description and SEO texts straight from the shop, each field with a hash and whether the platform can write it.categories_content_getandGET /categories/:guid/content?market=(scopecategory-content:read) return the same for a category.products_content_change_draftandcategories_content_change_draft(MCP only, sensitive scopesproduct-content:draftandcategory-content:draft) propose new texts, up to 30 items at once. They accept content fields only; price, stock, availability, code, EAN or name cannot be changed this way. HTML is validated: no script except one JSON-LD FAQPage block, noon…,javascript:oriframe. On approval the text is compared with the shop’s current state, and if someone changed it in the meantime nothing is written (CHANGED_SINCE_DRAFT). If the shop alters the text when saving, the result says so (MODIFIED_BY_PLATFORM). Proposals are approved under Warehouse → Product changes. On WooCommerce, a draft containing a script (including JSON-LD) or a backslash is blocked (PLATFORM_STRIPS_SCRIPT,PLATFORM_STRIPS_BACKSLASH): WordPress removes them when saving and customers would see the rest as text.products_content_policyandGET /product-content/policy?market=(scopeproduct-content:read) tell you, without calling the shop, what your key may do with texts on a given shop: whether it may read (readEnabled) and propose (draftEnabled, proposals over MCP only), which fields the platform writes (supportedFields; SEO fields on WooCommerce only with an SEO plugin), the approval mode (approvalMode:human,autonomousordisabled) and whether a proposal is written automatically (autonomousWriteEnabled), proposal limits and the hash algorithm (sha256). A paused shop, an unsupported platform or a read-only shop key are astatusandreasonin the response, not an error. Thecategoryfield carries the same for categories. ThestructuredDatafield tells whether the platform keeps structured data in the product description: on WooCommerce it does not (NOT_SUPPORTED,PLATFORM_STRIPS_SCRIPT; structured data there is managed by the store theme,THEME_MANAGED), on Shoptet it does (oneFAQPageblock).- Autonomous writing. By default every proposal (claims settings and routes, product and category texts) is written only when a person approves it. An administrator can switch it on per area under Settings → API & MCP → Writing via AI. The proposal is then written immediately, the same way as an approval, on behalf of the person who granted the AI access, and only if that person has the right to approve the change right now. Otherwise the proposal waits and the response says why. Every change of the mode is recorded.
Existing keys and consents do not inherit the new scopes; a new consent is needed.
Outbound webhooks
Section titled “Outbound webhooks”REST and MCP are reading on demand. When your system should learn about an event immediately — a new order, payment, status change, shipment, delivery, stock movement, invoice, claim — it subscribes over outbound webhooks: MitoOps sends a short envelope with identifiers to your endpoint, signed with HMAC-SHA256, with retries on failure and a delivery log. The system then loads the detail over REST.
Subscriptions are created by a person in the app on the same screen as keys; over REST and MCP endpoints are only read (webhooks:read, without the secret). An endpoint can also be used as an automation step. Details in outbound webhooks.
Account limits
Section titled “Account limits”API & MCP and webhooks are part of every paid plan from Start up. Plans differ in the number of active keys and endpoints, not in what can be read:
| Plan | API & MCP | Active access keys | Webhook endpoints |
|---|---|---|---|
| Trial | — | 0 | 0 |
| Beginner | — | 0 | 0 |
| Start | yes | 1 | 5 |
| Growth | yes | 2 | 20 |
| Pro | yes | 5 | 50 |
| Custom | yes | by agreement | by agreement |
The server enforces the limits: an attempt to add a key or endpoint above the limit is rejected with an explanation. Replacing a key or rotating an endpoint secret does not use up a slot. Downgrading does not revoke existing keys or endpoints — a new one just cannot be created until the count drops below the new cap. Connecting over OAuth does not consume a key.
Current values for your account including usage (active automations, runs this month, e-mails, credits) are returned by account_entitlements / GET /account/entitlements with the account:read scope. It carries only the plan, features and limits — no billing data. The current price list is at mitoops.com/en/cennik.
Call limits
Section titled “Call limits”| Limit | Measured on | How much |
|---|---|---|
| before authentication | the address you call from | 300 calls / 60 s |
| after authentication | the specific key | 600 calls / 60 s |
The first prevents key guessing, the second is yours and shared with nobody. Exceeding it is 429 with RateLimit-* headers. It is not a plan quantity — calls are not billed.
Errors
Section titled “Errors”An error response always has the same shape and carries a code:
{ "error": { "code": "store_required", "message": "…", "requestId": "…" } }| Status | Code | When |
|---|---|---|
400 |
invalid_request |
a parameter does not match the contract (bad date, reversed period, invalid cursor) |
400 |
store_required |
a call over shop data without market |
401 |
unauthorized |
missing, unknown, revoked or invalid key |
403 |
forbidden |
the key lacks the required scope |
403 |
store_forbidden |
a shop outside the key’s scope |
404 |
not_found |
the record does not exist (also when it belongs to another shop) |
405 |
— | anything other than GET (REST) |
409 |
conflict |
the draft write hit another version, a reused clientRequestId or a changed catalogue (MCP) |
429 |
rate_limited |
technical call limit exceeded |
The reason for a 401 is not distinguished — the difference would help whoever is guessing keys. Quote the requestId when reporting a problem to support. Over MCP an error the assistant can recover from arrives as a tool result flagged isError; a protocol error as a JSON-RPC error.
Examples
Section titled “Examples”# Orders for a period, pagedcurl -H "Authorization: Bearer <your key>" \ "https://<your address>/api/v1/orders?market=en&from=2026-08-01&to=2026-08-31&limit=50"
# Delivery statistics for Augustcurl -H "Authorization: Bearer <your key>" \ "https://<your address>/api/v1/shipping/stats?market=en&from=2026-08-01&to=2026-08-31"
# Claims statistics for Augustcurl -H "Authorization: Bearer <your key>" \ "https://<your address>/api/v1/claims/statistics?market=en&from=2026-08-01&to=2026-08-31"
# Plan and account limits with usagecurl -H "Authorization: Bearer <your key>" \ "https://<your address>/api/v1/account/entitlements"Questions Claude.ai answers from MitoOps data once connected: “What was the median delivery time of DHL and GLS in August?”, “How many orders came from ChatGPT?”, “What is the margin of product X over the last month?” (with purchase-prices:read), “How many claims are overdue?”, “Propose an automation that sends a reminder three days after an unpaid order” (with automations:write — a disabled draft is created), “Rename the Backorder availability on the SK shop to Ships in 5 days” (with availabilities:draft a proposal is created, which you write by approving it in the app).
Security
Section titled “Security”- Tenant isolation. The client comes exclusively from the credential; every client has its own database.
- Shop scope is the intersection of the credential’s list and the shops connected at that moment. On calls over one shop’s data
marketis required — a missing shop is400, a shop outside the scope403. - The person’s rights. The consent screen offers only scopes the signed-in person has themselves; the account’s own permission set decides.
- The limits of every write are enforced by the service, not by an annotation: an automation draft is always created disabled, a published automation is never changed over MCP, and a proposed availability change writes nothing to the shop until a person approves it in the app.
- Validity and revocation. An OAuth access token lasts an hour, a refresh token 30 days; a revoked consent stops every token derived from it. Keys can be revoked or replaced immediately.
- Audit. Every call is recorded with the capability name, the interface and a fingerprint of the input — without values.
- What you cannot rely on: non-public application routes (the interface is
/api/v1and/api/mcp, nothing else), direct database access (does not exist) and credentials (the interface never returns them).