{"openapi":"3.0.3","info":{"title":"Simplus Public API","version":"0.0.4","description":"The Simplus public API lets a business call Simplus programmatically with an API key,\nwithout going through the Simplus app.\n\n## Authentication\n\nEvery request carries an API key as a bearer token:\n\n    Authorization: Bearer 7b1f5e0c-9a2d-4f3b-8c61-2d9e4a7f0b55\n\nA key is issued from Simplus by the business owner and is shown exactly once, when it is\ncreated. Simplus stores only its hash, so a lost key is replaced, never recovered.\n\nA key is bound to one business, optionally narrowed to one outlet, and carries an\nexplicit set of permissions. It can only ever read or write what those permissions\nallow, for that business. Revoke a key from Simplus the moment it leaks.\n\n## Versioning\n\nThe API is versioned by release date: `/public/{YYYY-MM-DD}/...`. Pick the date that was\ncurrent when you integrated and keep sending it; a published date never changes shape,\nso nothing we release afterwards can break your integration. Move to a newer date when\nyou want what it added.\n\nPublished dates are listed in the `version` server variable below.\n\n## Responses\n\nUnlike the app-facing Simplus API, this API answers with real HTTP status codes.\n\nA success is `200` with the payload under `data`:\n\n    {\"success\": true, \"data\": {...}}\n\nA failure carries a Simplus support code and a message:\n\n    {\"success\": false, \"code\": 5197, \"message\": \"API key lacks the required permission\"}\n\nQuote `code` when contacting support. The status code is the contract; treat an\nunrecognised `code` as the status it arrived with.\n"},"servers":[{"url":"https://{host}/public/{version}","description":"Simplus public API","variables":{"host":{"default":"app.simplus.id","description":"The Simplus host. Override it only if Simplus gave your business a different one.\n"},"version":{"default":"2026-09-17","description":"The release date of the API version you integrated against.","enum":["2026-09-17"]}}}],"security":[{"ApiKeyBearer":[]}],"tags":[{"name":"Business","description":"The business the key belongs to, and its outlets."},{"name":"Inventory","description":"Products, variants and stock."}],"paths":{"/business":{"get":{"tags":["Business"],"operationId":"getBusiness","summary":"Get the business this key belongs to","description":"🔓 **Permission required:** none\n\nReturns the business this key was issued for, including the `timezone` every date and\ntime in Simplus is displayed in.\n","responses":{"200":{"description":"The business.","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/Business"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/UnprocessableEntity"},"500":{"$ref":"#/components/responses/InternalError"},"502":{"$ref":"#/components/responses/BadGateway"}}}},"/business/outlets":{"get":{"tags":["Business"],"operationId":"listOutlets","summary":"List the business's outlets","description":"🔓 **Permission required:** none\n\nReturns the outlets this key can see, which is what names the `outlet_id` on every stock\nline.\n","responses":{"200":{"description":"The outlets the key can see.","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/OutletList"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/UnprocessableEntity"},"500":{"$ref":"#/components/responses/InternalError"},"502":{"$ref":"#/components/responses/BadGateway"}}}},"/inventory/products":{"get":{"tags":["Inventory"],"operationId":"searchProducts","summary":"Search products by name","description":"🔒 **Permission required:** Melihat produk\n\nFinds your business's products by name (case-insensitive, word by word and\ntypo-tolerant), answering with ids and names only, best match first.\n","parameters":[{"name":"query","in":"query","required":true,"description":"What to look for in the product name. Split into words; each must match the start of a word in the name, or a word it is a plausible mistyping of, in any order. Surrounding spaces are ignored.","schema":{"type":"string","minLength":1},"example":"kopi"},{"name":"limit","in":"query","required":false,"description":"How many products to return, 1-20. Defaults to 10.","schema":{"type":"integer","minimum":1,"maximum":20,"default":10},"example":10}],"responses":{"200":{"description":"The products that matched.","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/ProductSearchResult"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/UnprocessableEntity"},"500":{"$ref":"#/components/responses/InternalError"},"502":{"$ref":"#/components/responses/BadGateway"}}}},"/inventory/products/{product_id}":{"get":{"tags":["Inventory"],"operationId":"getProduct","summary":"Get a product","description":"🔒 **Permission required:** Melihat produk\n\nReturns one product of your business, with its variants and the stock each variant holds\nper outlet.\n","parameters":[{"name":"product_id","in":"path","required":true,"description":"The product's Simplus id.","schema":{"type":"string","format":"uuid"},"example":"4f6a1d2e-8b90-4c31-a5d7-6e2f0b8c1a93"}],"responses":{"200":{"description":"The product.","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/Product"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/UnprocessableEntity"},"500":{"$ref":"#/components/responses/InternalError"},"502":{"$ref":"#/components/responses/BadGateway"}}}},"/inventory/stocks":{"get":{"tags":["Inventory"],"operationId":"getStocks","summary":"Get stock and price for several products","description":"🔒 **Permission required:** Melihat produk\n\nReturns up to 100 products at once, each with its variants, their selling prices and the\nstock they hold per outlet.\n","parameters":[{"name":"product_ids","in":"query","required":true,"description":"Product ids, comma-separated, 1-100 of them. Duplicates are read once. Anything\nthat is not a product id is `422`, including an empty list.\n","schema":{"type":"string"},"example":"4f6a1d2e-8b90-4c31-a5d7-6e2f0b8c1a93,7c3e9b41-2d58-4a6f-9e10-3b8d5c7a2f64"}],"responses":{"200":{"description":"The products that were found, in the order Simplus holds them.","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/StockList"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/UnprocessableEntity"},"500":{"$ref":"#/components/responses/InternalError"},"502":{"$ref":"#/components/responses/BadGateway"}}}}},"components":{"securitySchemes":{"ApiKeyBearer":{"type":"http","scheme":"bearer","description":"The API key exactly as Simplus issued it, sent as `Authorization: Bearer <key>`.\nA key is a UUID; anything else is rejected as an invalid key.\n"}},"schemas":{"Business":{"type":"object","required":["id","name","category","timezone","image_url"],"properties":{"id":{"type":"string","format":"uuid","description":"The business's Simplus id.","example":"6b0f2c14-9d3a-4e7f-8b52-1c4a7d9e0f36"},"name":{"type":"string","example":"Warung Kopi Sederhana"},"category":{"type":"string","description":"The line of business it was registered under, as Simplus spells it internally.\nTreat it as an opaque label: the list grows, so an unrecognised value is not an\nerror.\n","example":"MAKANANMINUMAN"},"timezone":{"type":"string","description":"The IANA timezone the business operates in. Simplus shows its own users every\ndate and time in this zone, so a report you generate should use it too.\n","example":"Asia/Jakarta"},"image_url":{"type":"string","nullable":true,"description":"A URL for the business's logo, or null if it has none.","example":"https://app.simplus.id/storage/business/6b0f2c14-9d3a-4e7f-8b52-1c4a7d9e0f36.png"}}},"OutletList":{"type":"object","required":["outlets"],"properties":{"outlets":{"type":"array","description":"Every outlet the key can see: all of the business's, or just the one the key\nis narrowed to.\n","items":{"$ref":"#/components/schemas/Outlet"}}}},"Outlet":{"type":"object","required":["id","name","is_active"],"properties":{"id":{"type":"string","format":"uuid","description":"The outlet's Simplus id. This is the `outlet_id` that appears on every stock\nline.\n","example":"2a3b4c5d-6e7f-4a8b-9c0d-1e2f3a4b5c6d"},"name":{"type":"string","example":"Cabang Kemang"},"is_active":{"type":"boolean","description":"Whether the outlet is open for business right now: activated, and not past\nits expiry. An inactive outlet is still returned, and stock recorded against it\nin the past is still reported.\n","example":true}}},"ProductSearchResult":{"type":"object","required":["products","total"],"properties":{"products":{"type":"array","description":"The matching products, best match first, at most `limit` of them.","items":{"$ref":"#/components/schemas/ProductSummary"}},"total":{"type":"integer","description":"How many products matched in all, before `limit` was applied. Greater than the\nlength of `products` means there is more than this page.\n","example":3}}},"ProductSummary":{"type":"object","required":["id","name","category_id","is_hidden"],"properties":{"id":{"type":"string","format":"uuid","description":"The product's Simplus id. This is what `GET /inventory/stocks` and\n`GET /inventory/products/{product_id}` take.\n","example":"4f6a1d2e-8b90-4c31-a5d7-6e2f0b8c1a93"},"name":{"type":"string","example":"Kopi Susu"},"category_id":{"type":"string","format":"uuid","nullable":true,"description":"The category the product belongs to, if any.","example":"1c2b3a4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"},"is_hidden":{"type":"boolean","description":"Whether the product is hidden in Simplus. Hidden products are returned; what\na hidden product means is the business's decision, not this API's, so skip them\nyourself if you are quoting to a customer.\n","example":false}}},"StockList":{"type":"object","required":["products"],"properties":{"products":{"type":"array","description":"One entry per id that matched a product of your business. Ids that matched\nnothing are absent; the list is empty if none of them did.\n","items":{"$ref":"#/components/schemas/Product"}}}},"Product":{"type":"object","required":["id","name","unit","category_id","is_hidden","variant_types","variants"],"properties":{"id":{"type":"string","format":"uuid","description":"The product's Simplus id.","example":"4f6a1d2e-8b90-4c31-a5d7-6e2f0b8c1a93"},"name":{"type":"string","example":"Kaos Polos"},"unit":{"type":"string","nullable":true,"description":"The unit the product is counted in, if it has one.","example":"pcs"},"category_id":{"type":"string","format":"uuid","nullable":true,"description":"The category the product belongs to, if any.","example":"1c2b3a4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"},"is_hidden":{"type":"boolean","description":"Whether the product is hidden in Simplus.","example":false},"variant_types":{"type":"array","description":"What the variations of each variant mean, in order. `[\"Warna\", \"Ukuran\"]` says\na variant's `variations` reads colour first, size second. Empty for a product\nthat has no variant axes.\n","items":{"type":"string"},"example":["Warna","Ukuran"]},"variants":{"type":"array","description":"Every variant of the product. A product with no variant axes still has exactly\none variant: that is where its SKU, price and stock live.\n","items":{"$ref":"#/components/schemas/Variant"}}}},"Variant":{"type":"object","required":["id","sku","selling_price","variations","stocks"],"properties":{"id":{"type":"string","format":"uuid","description":"The variant's Simplus id.","example":"9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a"},"sku":{"type":"string","nullable":true,"example":"KAOS-MERAH-L"},"selling_price":{"type":"number","format":"double","description":"The variant's selling price, in the business's currency.","example":75000},"variations":{"type":"array","description":"This variant's value for each entry of the product's `variant_types`, in the\nsame order.\n","items":{"type":"string"},"example":["Merah","L"]},"stocks":{"type":"array","description":"Stock held per outlet. An outlet the variant has never been stocked at may be\nabsent rather than reported as zero.\n","items":{"$ref":"#/components/schemas/Stock"}}}},"Stock":{"type":"object","required":["outlet_id","quantity"],"properties":{"outlet_id":{"type":"string","format":"uuid","description":"The outlet holding this stock.","example":"2a3b4c5d-6e7f-4a8b-9c0d-1e2f3a4b5c6d"},"quantity":{"type":"number","format":"double","description":"Units on hand. Can be negative where stock was oversold.","example":12}}},"Error":{"type":"object","required":["success","code","message"],"properties":{"success":{"type":"boolean","enum":[false]},"code":{"type":"integer","description":"The Simplus support code for this failure. Quote it in support requests.","example":5197},"message":{"type":"string","description":"A short description of the failure. Wording may change; do not match on it.","example":"API key lacks the required permission"}}}},"responses":{"Unauthorized":{"x-simplus-codes":[5183,5192,5193],"description":"The key is missing, malformed, unknown or revoked. Unknown and revoked are\ndeliberately the same answer.\n\nCodes: `5192` no key was sent, `5183` the key is not a well-formed key,\n`5193` the key is unknown or revoked.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"success":false,"code":5193,"message":"Invalid or revoked API key"}}}},"Forbidden":{"x-simplus-codes":[5196,5197],"description":"A valid key that is not allowed to do this.\n\nCodes: `5196` the resource belongs to another business, or the key is not scoped to\nit; `5197` the key lacks the permission this endpoint requires.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"success":false,"code":5197,"message":"API key lacks the required permission"}}}},"NotFound":{"x-simplus-codes":[5199],"description":"No such resource, or no such endpoint or version date under `/public`.\n\nCode: `5199`.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"success":false,"code":5199,"message":"Product not found"}}}},"UnprocessableEntity":{"x-simplus-codes":[881,5198],"description":"The request itself was malformed: a parameter missing, or not of the shape this\nendpoint accepts.\n\nCodes: `881`, `5198`.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"success":false,"code":5198,"message":"Invalid request"}}}},"InternalError":{"x-simplus-codes":[5195],"description":"Something failed on our side. The failure is reported to us; retry, and contact\nsupport if it persists.\n\nCode: `5195`.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"success":false,"code":5195,"message":"Internal error"}}}},"BadGateway":{"x-simplus-codes":[5194,5195],"description":"We could not complete the call to the part of Simplus that owns this data: it did\nnot answer in time, or refused for a reason this API does not translate. Safe to\nretry.\n\nCodes: `5194` the call could not be completed at all, `5195` it was refused for a\nreason with no public meaning.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"success":false,"code":5194,"message":"Upstream service unavailable"}}}}}}}