CompuDime API docs

Authentication

Send your API key with every call. The key decides which store you read and which endpoints you may call.

Send the key

Authorization: Bearer <your key>

Send it on every request, over HTTPS. Only the status calls and the OpenAPI document need no key.

Keys

You create and revoke keys at account.compudime.com. A key belongs to one store.

Key starts withWhat it is
cc_test_ or cd_test_A test key. Its calls use the paying organization's monthly sandbox allowance, never overage, and work before the store has a card on file. The billing block says "mode": "test". Its orders are simulated and never reach the store (see Test orders).
cc_live_ or cd_live_A live key. Its calls are billed to the paying organization's plan.

Both read the same store data. Only orders differ: a test key's orders never reach the store. Build with a test key, and switch to a live key when you go live. cd_ keys are older keys; they keep working.

Keep keys on your server. Never put one in source control, in a web page or in a mobile app. If a key leaks, revoke it and create a new one.

Working across stores

A developer who builds for many stores gets one key per store, once each store's owner approves. There is no key for several stores: for ten stores you hold ten keys, and GET /v1/me names the store a key reads.

Test orders

An order you send with a test key (POST /v1/orders) is checked exactly like a live key's order: the body, the lines, the Idempotency-Key and what your key may do. You get the same 202 and the same body. But the order is simulated. It never reaches the store's POS.

What a test order does not check: the store looks up each productCode and sets the prices only when a live order reaches it. A simulated order proves your request is right, not that the store carries the products.

Request ids

Send X-Request-Id with an id of your own: 1 to 128 letters, digits, dots, underscores or dashes, starting with a letter or digit. It comes back as requestId in the body and in the X-Request-Id header. Without one, the API makes one up. Log it, and quote it when you write to support.

What a key may do

A key carries one or more capabilities. Each endpoint needs one. GET /v1/capabilities is free and says what your key carries. The store owner decides which capabilities a store turns on.

GET /v1/me, also free, describes the key itself: its integration and access level, its store, the fields it may ask for on each endpoint it can call, its rate limit and, for the store's own keys, the store's credits. It never shows the key.

accounting-data

catalog-feed

customer-access

sales-data

order-intake

purchasing-data

Each endpoint also names a scope (x-compudime-scope in the reference). Scopes come with the capability; you do not ask for them.

Access levels: own or all customers

Every integration has an access level, own or all. The store owner sets it. GET /v1/capabilities returns it as accessLevel. It changes the customer reads and nothing else.

A customer outside your level is answered like a customer the store does not have. You never get a 403 for it, so an answer never tells you a customer exists. A cursor belongs to the level it was made at: if the owner changes your level, start the listing again.

EndpointAt ownAt all
GET /v1/accounting/journal-entriesThe level does not change this operation: own and all return the same data. Scope accounting.read.The level does not change this operation: own and all return the same data. Scope accounting.read.
GET /v1/accounting/mappingThe level does not change this operation: own and all return the same data. Scope accounting.read.The level does not change this operation: own and all return the same data. Scope accounting.read.
GET /v1/accounting/sales-summariesThe level does not change this operation: own and all return the same data. Scope accounting.read.The level does not change this operation: own and all return the same data. Scope accounting.read.
GET /v1/brandsThe level does not change this operation: own and all return the same data. Scope catalog.reference.read.The level does not change this operation: own and all return the same data. Scope catalog.reference.read.
GET /v1/capabilitiesThe level does not change this operation: own and all return the same data. Scope platform.capabilities.read.The level does not change this operation: own and all return the same data. Scope platform.capabilities.read.
GET /v1/catalog/snapshots/currentThe level does not change this operation: own and all return the same data. Scope catalog.snapshots.read.The level does not change this operation: own and all return the same data. Scope catalog.snapshots.read.
GET /v1/categoriesThe level does not change this operation: own and all return the same data. Scope catalog.reference.read.The level does not change this operation: own and all return the same data. Scope catalog.reference.read.
GET /v1/customersPages only the customers linked to this integration: the customers its own orders (POST /v1/orders) landed on in the store's POS, matched by the customer's main phone. They come in phone order, at most 25 a page whatever limit asks, and a page can hold fewer (even none) while nextCursor is set, when a linked customer is no longer on file. The cursor is this level's own; a cursor issued at the other level is a 400. modifiedSince keeps the linked customers modified at or after it, and every linked customer without a modifiedAt. An integration with no linked customer gets an empty page. Scope customers.read.self.Pages the store's whole customer file. Scope customers.read.all.
GET /v1/customers/lookupReturns only the customers linked to this integration among the phone's matches. When none is linked the answer is found:false with no customers, exactly like a phone the store does not know, so it never confirms that a customer exists. Scope customers.read.self.Returns every customer on file for the phone. Scope customers.read.all.
GET /v1/customers/{posCustomerId}Returns the customer only when it is linked to this integration (its main phone is the phone of one of this integration's orders that landed in the POS). Any other customer is 404 customer_not_found, exactly like a customer the store does not have, so the answer never confirms that a customer exists. Scope customers.read.self.Returns any customer of the store. Scope customers.read.all.
GET /v1/delivery/routesThe level does not change this operation: own and all return the same data. Scope sales.read.The level does not change this operation: own and all return the same data. Scope sales.read.
GET /v1/inventory/onhandThe level does not change this operation: own and all return the same data. Scope sales.read.The level does not change this operation: own and all return the same data. Scope sales.read.
GET /v1/invoicesThe level does not change this operation: own and all return the same data. Scope sales.read.The level does not change this operation: own and all return the same data. Scope sales.read.
GET /v1/invoices/external/{externalId}The level does not change this operation: own and all return the same data. Scope sales.read.The level does not change this operation: own and all return the same data. Scope sales.read.
GET /v1/invoices/{posInvoiceId}The level does not change this operation: own and all return the same data. Scope sales.read.The level does not change this operation: own and all return the same data. Scope sales.read.
GET /v1/meThe level does not change this operation: own and all return the same data. Scope platform.me.read.The level does not change this operation: own and all return the same data. Scope platform.me.read.
POST /v1/ordersThe order belongs to this integration at either level, and only this integration reads it back. Scope orders.write.The order belongs to this integration at either level, and only this integration reads it back. Scope orders.write.
GET /v1/orders/external/{externalOrderId}Only the orders this integration created, at either level: all does not widen the order reads. Scope orders.read.Only the orders this integration created, at either level: all does not widen the order reads. Scope orders.read.
GET /v1/orders/{orderId}Only the orders this integration created, at either level: all does not widen the order reads. Scope orders.read.Only the orders this integration created, at either level: all does not widen the order reads. Scope orders.read.
GET /v1/productsThe level does not change this operation: own and all return the same data. Scope catalog.products.read.The level does not change this operation: own and all return the same data. Scope catalog.products.read.
GET /v1/products/lookup/{code}The level does not change this operation: own and all return the same data. Scope catalog.products.read.The level does not change this operation: own and all return the same data. Scope catalog.products.read.
GET /v1/products/{productCode}The level does not change this operation: own and all return the same data. Scope catalog.products.read.The level does not change this operation: own and all return the same data. Scope catalog.products.read.
GET /v1/promotionsThe level does not change this operation: own and all return the same data. Scope catalog.products.read.The level does not change this operation: own and all return the same data. Scope catalog.products.read.
GET /v1/promotions/mix-match/{groupId}The level does not change this operation: own and all return the same data. Scope catalog.products.read.The level does not change this operation: own and all return the same data. Scope catalog.products.read.
GET /v1/purchase-ordersThe level does not change this operation: own and all return the same data. Scope purchasing.read.The level does not change this operation: own and all return the same data. Scope purchasing.read.
GET /v1/purchase-orders/{posPurchaseOrderId}The level does not change this operation: own and all return the same data. Scope purchasing.read.The level does not change this operation: own and all return the same data. Scope purchasing.read.
GET /v1/reasonsThe level does not change this operation: own and all return the same data. Scope catalog.reference.read.The level does not change this operation: own and all return the same data. Scope catalog.reference.read.
GET /v1/receivingThe level does not change this operation: own and all return the same data. Scope purchasing.read.The level does not change this operation: own and all return the same data. Scope purchasing.read.
GET /v1/receiving/{posReceivingId}The level does not change this operation: own and all return the same data. Scope purchasing.read.The level does not change this operation: own and all return the same data. Scope purchasing.read.
GET /v1/sales/dailyThe level does not change this operation: own and all return the same data. Scope customers.read.all.The level does not change this operation: own and all return the same data. Scope customers.read.all.
GET /v1/sales/movementThe level does not change this operation: own and all return the same data. Scope sales.read.The level does not change this operation: own and all return the same data. Scope sales.read.
GET /v1/sales/zreportThe level does not change this operation: own and all return the same data. Scope sales.read.The level does not change this operation: own and all return the same data. Scope sales.read.
GET /v1/storeThe level does not change this operation: own and all return the same data. Scope catalog.reference.read.The level does not change this operation: own and all return the same data. Scope catalog.reference.read.
GET /v1/tagsThe level does not change this operation: own and all return the same data. Scope catalog.reference.read.The level does not change this operation: own and all return the same data. Scope catalog.reference.read.
GET /v1/tendersThe level does not change this operation: own and all return the same data. Scope customers.read.all.The level does not change this operation: own and all return the same data. Scope customers.read.all.
GET /v1/ticketsThe level does not change this operation: own and all return the same data. Scope sales.read.The level does not change this operation: own and all return the same data. Scope sales.read.
GET /v1/tickets/{ticketId}The level does not change this operation: own and all return the same data. Scope sales.read.The level does not change this operation: own and all return the same data. Scope sales.read.
GET /v1/usage/currentThe level does not change this operation: own and all return the same data. Scope platform.usage.read.The level does not change this operation: own and all return the same data. Scope platform.usage.read.
GET /v1/webhooksThe level does not change this operation: own and all return the same data. Scope webhooks.read.The level does not change this operation: own and all return the same data. Scope webhooks.read.
POST /v1/webhooksThe level does not change this operation: own and all return the same data. Scope orders.webhooks.The level does not change this operation: own and all return the same data. Scope orders.webhooks.
DELETE /v1/webhooks/{webhookId}The level does not change this operation: own and all return the same data. Scope webhooks.write.The level does not change this operation: own and all return the same data. Scope webhooks.write.
GET /v1/webhooks/{webhookId}The level does not change this operation: own and all return the same data. Scope webhooks.read.The level does not change this operation: own and all return the same data. Scope webhooks.read.
GET /v1/webhooks/{webhookId}/deliveriesThe level does not change this operation: own and all return the same data. Scope webhooks.read.The level does not change this operation: own and all return the same data. Scope webhooks.read.
POST /v1/webhooks/{webhookId}/rotate-secretThe level does not change this operation: own and all return the same data. Scope orders.webhooks.The level does not change this operation: own and all return the same data. Scope orders.webhooks.
POST /v1/webhooks/{webhookId}/testThe level does not change this operation: own and all return the same data. Scope orders.webhooks.The level does not change this operation: own and all return the same data. Scope orders.webhooks.

Scoped keys

A key can carry a fixed data scope, set by the store owner:

A scoped key pages, looks up and counts only inside its slice. There is no parameter that widens it. Reads whose totals cover every product of the store (invoices, delivery routes, purchase orders, receiving, register tickets and the Z report) answer a scoped key with 422 scope_not_applicable, which is never charged.