{"openapi":"3.0.3","info":{"title":"Simplus Public API","version":"0.0.32","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\n## Webhooks\n\nSimplus can also call you when something changes. Start with the\n[webhook introduction](https://docs.simplus.id/integration/webhook/pengenalan), then see\n**Webhooks** in the sidebar for the events you can subscribe to.\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."},{"name":"Sales","description":"Sales, returns and refunds."},{"name":"Customer","description":"Customers and their points."},{"name":"Wallet","description":"Where payments are received, such as cash or a bank account."},{"name":"Webhook Overview","x-displayName":"Webhook","description":"Simplus sends a `POST` to your endpoint when something changes, with a JSON body like\n`{\"type\": \"sales.persisted\", \"data\": {...}}`. Each event below shows a full example.\n\nVerify the `svix-signature` header against the raw body, then answer `2xx` quickly;\nanything else is retried. Events can arrive out of order or more than once, so key on\n`data.id` and drop repeats by `svix-id`.\n\nSetup and signature verification are covered in the\n[webhook introduction](https://docs.simplus.id/integration/webhook/pengenalan).\n"},{"name":"Webhook Events","description":"The events Simplus can send to your endpoint, one per change you can subscribe to.\n"}],"x-tagGroups":[{"name":"APIs","tags":["Business","Inventory","Sales","Customer","Wallet"]},{"name":"Webhooks","tags":["Webhook Overview","Webhook Events"]}],"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"}}}},"/sales/transactions":{"get":{"tags":["Sales"],"operationId":"listSales","summary":"Sync sales created or changed since a cursor","description":"🔒 **Permission required:** Melihat riwayat penjualan\n\nSales created or changed after `since` (new, edited, paid, refunded or voided).\n\n**Sync:** start with `since=0`, then pass `next_since` while `has_more` is `true`.\nSave the last `next_since` and poll with it. Changed records come again; upsert by `id`.\n","parameters":[{"name":"since","in":"query","required":false,"description":"The previous page's `next_since`, or `0` to start from the beginning.","schema":{"type":"integer","minimum":0,"default":0},"example":0},{"name":"limit","in":"query","required":false,"description":"How many to return, 1-100. Defaults to 50.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"example":50},{"name":"outlet_id","in":"query","required":false,"description":"Only this outlet. An outlet-scoped key asking for another outlet gets `403`.","schema":{"type":"string","format":"uuid"},"example":"2a3b4c5d-6e7f-4a8b-9c0d-1e2f3a4b5c6d"}],"responses":{"200":{"description":"One page of sales.","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/SalesChangeList"}}}}}},"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"}}}},"/sales/transactions/lookup":{"get":{"tags":["Sales"],"operationId":"lookupSales","summary":"Find a sale by its order number","description":"🔒 **Permission required:** Melihat riwayat penjualan\n\nThe latest sale with this order number.\n","parameters":[{"name":"order_number","in":"query","required":true,"description":"The order number on the receipt.","schema":{"type":"string","minLength":1,"maxLength":100},"example":"SO-2026-0001"}],"responses":{"200":{"description":"The sale.","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/Sales"}}}}}},"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"}}}},"/sales/transactions/{sales_id}":{"get":{"tags":["Sales"],"operationId":"getSales","summary":"Get a sale","description":"🔒 **Permission required:** Melihat riwayat penjualan\n\nOne sale, including voided ones.\n","parameters":[{"name":"sales_id","in":"path","required":true,"description":"The sale's Simplus id.","schema":{"type":"string","format":"uuid"},"example":"6f1c1d2e-3b4a-4c5d-8e9f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"The sale.","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/Sales"}}}}}},"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"}}}},"/sales/returns":{"get":{"tags":["Sales"],"operationId":"listSalesReturns","summary":"Sync sales returns and refunds created, changed or deleted since a cursor","description":"🔒 **Permission required:** Melihat Retur Penjualan\n\nReturns and refunds created, changed or deleted after `since`.\n\n**Sync:** start with `since=0`, then pass `next_since` while `has_more` is `true`.\nSave the last `next_since` and poll with it. Changed records come again; upsert by `id`.\n","parameters":[{"name":"since","in":"query","required":false,"description":"The previous page's `next_since`, or `0` to start from the beginning.","schema":{"type":"integer","minimum":0,"default":0},"example":0},{"name":"limit","in":"query","required":false,"description":"How many to return, 1-100. Defaults to 50.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"example":50},{"name":"outlet_id","in":"query","required":false,"description":"Only this outlet. An outlet-scoped key asking for another outlet gets `403`.","schema":{"type":"string","format":"uuid"},"example":"2a3b4c5d-6e7f-4a8b-9c0d-1e2f3a4b5c6d"}],"responses":{"200":{"description":"One page of sales returns.","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/SalesReturnChangeList"}}}}}},"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"}}}},"/sales/returns/{sales_return_id}":{"get":{"tags":["Sales"],"operationId":"getSalesReturn","summary":"Get a sales return","description":"🔒 **Permission required:** Melihat Retur Penjualan\n\nOne return or refund.\n","parameters":[{"name":"sales_return_id","in":"path","required":true,"description":"The sales return's Simplus id.","schema":{"type":"string","format":"uuid"},"example":"7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d"}],"responses":{"200":{"description":"The sales return.","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/SalesReturn"}}}}}},"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"}}}},"/customers":{"get":{"tags":["Customer"],"operationId":"listCustomers","summary":"Sync customers created, changed or deleted since a cursor","description":"🔒 **Permission required:** Melihat Semua Pelanggan\n\nCustomers created, changed or deleted after `since`. Matches `Sales.customer.id`.\n\n**Sync:** start with `since=0`, then pass `next_since` while `has_more` is `true`.\nSave the last `next_since` and poll with it. Changed records come again; upsert by `id`.\n","parameters":[{"name":"since","in":"query","required":false,"description":"The previous page's `next_since`, or `0` to start from the beginning.","schema":{"type":"integer","minimum":0,"default":0},"example":0},{"name":"limit","in":"query","required":false,"description":"How many to return, 1-100. Defaults to 50.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"example":50}],"responses":{"200":{"description":"One page of customers.","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/CustomerChangeList"}}}}}},"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"}}}},"/wallets":{"get":{"tags":["Wallet"],"operationId":"listWallets","summary":"List the business's wallets","description":"🔒 **Permission required:** Melihat daftar dompet\n\nWallets the key can see, to name the `wallet_id` on payments and refunds.\n","responses":{"200":{"description":"The wallets.","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/WalletList"}}}}}},"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"}}}}},"x-webhooks":{"sales.persisted":{"post":{"operationId":"salesPersisted","tags":["Webhook Events"],"summary":"Sale Persisted","description":"Sent with type `sales.persisted` every time a sale is created or updated, for example\na new sale from the cashier, or a change to an existing sale's items, payments,\ncustomer or shipping.\n","parameters":[{"name":"svix-id","in":"header","required":true,"description":"The message id. A retried delivery carries the same id, so use it to drop\nduplicates.\n","schema":{"type":"string"},"example":"msg_2mQxK7l3a1v9TqXcRb8ZyJ0dE4f"},{"name":"svix-timestamp","in":"header","required":true,"description":"When the message was sent, as a Unix timestamp in seconds.","schema":{"type":"string"},"example":"1790000000"},{"name":"svix-signature","in":"header","required":true,"description":"The signature of the raw body. Verify it with your endpoint's signing secret\nbefore trusting the payload.\n","schema":{"type":"string"},"example":"v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4="}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["type","data"],"properties":{"type":{"type":"string","enum":["sales.persisted"],"description":"The event name. Always `sales.persisted`.","example":"sales.persisted"},"data":{"type":"object","description":"A sale, as it stands after the change that triggered the event.","required":["id","business_id","outlet_id","order_number","made_by","created_at","due_by","delivery_date","tax","items","additional_fields","shipping_fields","payments","paid_amount","last_paid_date","customer","non_member_name"],"properties":{"id":{"type":"string","format":"uuid","description":"The sale's id."},"business_id":{"type":"string","format":"uuid","description":"The business the sale belongs to."},"outlet_id":{"type":"string","format":"uuid","description":"The outlet the sale was made at."},"order_number":{"type":"string","description":"The number printed on the receipt.","example":"SO-2026-0001"},"made_by":{"type":"string","nullable":true,"description":"The name of the staff member who made the sale.","example":"Budi"},"created_at":{"type":"integer","description":"When the sale was made.","example":1790000000},"due_by":{"type":"integer","nullable":true,"description":"The payment due date, if there is one."},"delivery_date":{"type":"integer","nullable":true,"description":"The delivery date, if there is one."},"tax":{"type":"object","nullable":true,"description":"The tax on the sale, or null if it carries none.","required":["amount","calculation_type","type"],"properties":{"amount":{"type":"number","description":"The total tax.","example":3960},"calculation_type":{"type":"string","enum":["before_discount","after_discount"],"description":"Whether the tax is calculated on the price before or after discounts.","example":"after_discount"},"type":{"type":"string","enum":["inclusive","exclusive"],"description":"`inclusive` when the tax is already included in the prices, `exclusive` when it is\nadded on top of them.\n","example":"exclusive"}}},"items":{"type":"array","description":"The items sold.","items":{"type":"object","required":["product_id","product_type","name","unit","description","quantity","unit_price","discount","discount_per_qty","tax_rate"],"properties":{"product_id":{"type":"string","format":"uuid","description":"The product's id."},"product_type":{"type":"string","enum":["variant","bundle"],"description":"Whether `product_id` is a single variant or a bundle of products.","example":"variant"},"name":{"type":"string","description":"The product's name at the time of the sale.","example":"Kopi Susu Gula Aren"},"unit":{"type":"string","nullable":true,"description":"The product's unit.","example":"pcs"},"description":{"type":"string","nullable":true,"description":"A note on the item."},"quantity":{"type":"number","example":2},"unit_price":{"type":"number","example":18000},"discount":{"type":"number","description":"The total discount on the item.","example":0},"discount_per_qty":{"type":"number","description":"The discount per unit.","example":0},"tax_rate":{"type":"number","description":"The item's tax rate, in percent.","example":11}}}},"additional_fields":{"type":"array","description":"Extra charges, such as a service fee.","items":{"type":"object","required":["label","description","subtotal"],"properties":{"label":{"type":"string","description":"The charge's name.","example":"Biaya Layanan"},"description":{"type":"string","nullable":true},"subtotal":{"type":"number","example":2000}}}},"shipping_fields":{"type":"array","description":"Shipping details.","items":{"type":"object","required":["awb_number","shipping_method","rate","sender_address","recipient_address"],"properties":{"awb_number":{"type":"string","nullable":true,"description":"The tracking number."},"shipping_method":{"type":"string","nullable":true,"description":"The courier or shipping method.","example":"JNE REG"},"rate":{"type":"number","description":"The shipping cost.","example":15000},"sender_address":{"type":"string","nullable":true},"recipient_address":{"type":"string","nullable":true}}}},"payments":{"type":"array","description":"The payments made against the sale.","items":{"type":"object","required":["id","type","amount","paid_at"],"properties":{"id":{"type":"string","description":"The payment's id."},"type":{"type":"string","enum":["virtual_wallet","qris_yukk","qris_midtrans"],"description":"The payment method.","example":"virtual_wallet"},"amount":{"type":"number","example":39960},"paid_at":{"type":"integer","nullable":true,"description":"When the payment was made.","example":1790000000}}}},"paid_amount":{"type":"number","description":"The total paid so far.","example":39960},"last_paid_date":{"type":"integer","nullable":true,"description":"When the latest payment was made.","example":1790000000},"customer":{"type":"object","nullable":true,"description":"The member who bought, or null if the buyer is not a member.","required":["id","name","phone","email","member_code"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"Siti Rahma"},"phone":{"type":"string","nullable":true,"example":"081234567890"},"email":{"type":"string","nullable":true,"example":"siti@example.com"},"member_code":{"type":"string","nullable":true,"example":"MBR-0042"}}},"non_member_name":{"type":"string","nullable":true,"description":"The buyer's name, when the buyer is not a member.","example":"Andi"}}}},"example":{"type":"sales.persisted","data":{"id":"6f1c1d2e-3b4a-4c5d-8e9f-0a1b2c3d4e5f","business_id":"0b9c8d7e-6f5a-4b3c-2d1e-0f9a8b7c6d5e","outlet_id":"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d","order_number":"SO-2026-0001","made_by":"Budi","created_at":1790000000,"due_by":null,"delivery_date":null,"tax":{"amount":3960,"calculation_type":"after_discount","type":"exclusive"},"items":[{"product_id":"2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e","product_type":"variant","name":"Kopi Susu Gula Aren","unit":"pcs","description":null,"quantity":2,"unit_price":18000,"discount":0,"discount_per_qty":0,"tax_rate":11}],"additional_fields":[],"shipping_fields":[],"payments":[{"id":"3c4d5e6f-7a8b-4c9d-0e1f-2a3b4c5d6e7f","type":"virtual_wallet","amount":39960,"paid_at":1790000000}],"paid_amount":39960,"last_paid_date":1790000000,"customer":null,"non_member_name":"Andi"}}}}}},"responses":{"2XX":{"description":"Received. Answer as soon as the signature checks out; anything else is retried."}}}}},"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","enum":["STARTUP","TOKOONLINE","RESTORAN","TOSERBA","PERTANIAN","PERIKANAN","KERAJINAN","OTOMOTIF","MAKANANMINUMAN","PRODUKDIGITAL","PERALATANRUMAHTANGGA","KESEHATAN","ALATOLAHRAGA","PRODUKANAK","RETAIL","FASHION","JASA","LAIN"],"description":"The line of business it was registered under, as Simplus spells it internally.\n`STARTUP`, `TOKOONLINE`, `RESTORAN` and `TOSERBA` are retired and only found on\nolder businesses. The list grows, so treat an unrecognised value as `LAIN`\nrather than an error.\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}}},"SalesChangeList":{"type":"object","required":["sales","next_since","has_more"],"properties":{"sales":{"type":"array","description":"Oldest change first.","items":{"$ref":"#/components/schemas/Sales"}},"next_since":{"type":"integer","description":"Send as `since` next time.","example":1042},"has_more":{"type":"boolean","description":"Whether another page is waiting right now. Keep paging while `true`.","example":false}}},"Sales":{"type":"object","description":"A sale. Times are Unix seconds. Promo discounts are in `discount_per_qty`.\n","required":["id","order_number","outlet_id","outlet_name","created_at","status","cashier","customer","items","additional_fields","shipping_fields","tax","vouchers","payments","subtotal","grand_total","paid_amount","payment_status","sales_return_ids"],"properties":{"id":{"type":"string","format":"uuid","description":"The sale's Simplus id.","example":"6f1c1d2e-3b4a-4c5d-8e9f-0a1b2c3d4e5f"},"order_number":{"type":"string","description":"The number printed on the receipt (the invoice number).","example":"SO-2026-0001"},"outlet_id":{"type":"string","format":"uuid","description":"The outlet the sale was made at.","example":"2a3b4c5d-6e7f-4a8b-9c0d-1e2f3a4b5c6d"},"outlet_name":{"type":"string","example":"Cabang Kemang"},"created_at":{"type":"integer","description":"When the sale was made.","example":1790000000},"status":{"type":"string","enum":["active","voided"],"description":"`voided` when the sale was deleted.","example":"active"},"cashier":{"type":"object","description":"The staff member or owner who recorded the sale.","required":["id","name"],"properties":{"id":{"type":"string","format":"uuid","example":"8b9c0d1e-2f3a-4b4c-9d5e-6f7a8b9c0d1e"},"name":{"type":"string","nullable":true,"description":"Null if the account no longer exists.","example":"Budi"}}},"customer":{"type":"object","nullable":true,"description":"The buyer, or null if none was recorded.","required":["type","id","name","phone","member_code"],"properties":{"type":{"type":"string","enum":["member","non_member"],"description":"`member` has an `id`; `non_member` has only a name.","example":"member"},"id":{"type":"string","format":"uuid","nullable":true,"description":"The customer's id. Null for a non-member.","example":"4d5e6f7a-8b9c-4d0e-8f2a-3b4c5d6e7f8a"},"name":{"type":"string","nullable":true,"example":"Siti Rahma"},"phone":{"type":"string","nullable":true,"description":"The member's phone number. Null for a non-member.","example":"081234567890"},"member_code":{"type":"string","nullable":true,"description":"The member's code. Null for a non-member.","example":"MBR-0042"}}},"items":{"type":"array","description":"The items sold.","items":{"type":"object","required":["product_id","product_type","name","unit","description","quantity","unit_price","discount_per_qty","discount","tax_rate","subtotal"],"properties":{"product_id":{"type":"string","format":"uuid","description":"The variant's or bundle's id.","example":"9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a"},"product_type":{"type":"string","enum":["variant","bundle"],"description":"Whether `product_id` is a single variant or a bundle of products.","example":"variant"},"name":{"type":"string","nullable":true,"description":"The product's current name. Null if the product is gone.","example":"Kopi Susu Gula Aren"},"unit":{"type":"string","nullable":true,"example":"pcs"},"description":{"type":"string","nullable":true,"description":"A note on the item.","example":"Less sugar"},"quantity":{"type":"number","example":2},"unit_price":{"type":"number","description":"The price per unit before discount.","example":18000},"discount_per_qty":{"type":"number","description":"The discount per unit, promos included.","example":2000},"discount":{"type":"number","description":"Line discount.","example":4000},"tax_rate":{"type":"number","description":"The line's tax rate, in percent.","example":11},"subtotal":{"type":"number","description":"Line total after discount.","example":32000}}}},"additional_fields":{"type":"array","description":"Extra charges, such as a service fee.","items":{"type":"object","required":["label","description","amount"],"properties":{"label":{"type":"string","example":"Biaya Layanan"},"description":{"type":"string","nullable":true,"example":"Service fee"},"amount":{"type":"number","example":2000}}}},"shipping_fields":{"type":"array","description":"Shipments on the sale.","items":{"type":"object","required":["method","awb_number","rate"],"properties":{"method":{"type":"string","description":"The courier or shipping method.","example":"JNEREG19"},"awb_number":{"type":"string","nullable":true,"description":"The tracking number, once there is one.","example":"JN0012345678"},"rate":{"type":"number","description":"The shipping cost.","example":15000}}}},"tax":{"type":"object","nullable":true,"description":"The tax on the sale, or null if it carries none.","required":["amount","calculation_type","type"],"properties":{"amount":{"type":"number","example":3520},"calculation_type":{"type":"string","enum":["before_discount","after_discount"],"example":"after_discount"},"type":{"type":"string","enum":["inclusive","exclusive"],"description":"`inclusive` when the tax is already in the prices, `exclusive` when it is\nadded on top of them.\n","example":"exclusive"}}},"vouchers":{"type":"array","description":"Discount vouchers redeemed on the sale.","items":{"type":"object","required":["id","voucher_number","group_id","description","discount_amount"],"properties":{"id":{"type":"string","format":"uuid","description":"The voucher's id.","example":"5e6f7a8b-9c0d-4e1f-8a3b-4c5d6e7f8a9b"},"voucher_number":{"type":"string","nullable":true,"description":"The code the customer redeemed. Null if the voucher is gone.","example":"HEMAT10K-7Q2X"},"group_id":{"type":"string","format":"uuid","nullable":true,"description":"The voucher campaign it was issued from.","example":"6f7a8b9c-0d1e-4f2a-9b4c-5d6e7f8a9b0c"},"description":{"type":"string","nullable":true,"description":"The campaign's description.","example":"Potongan Rp10.000 untuk member"},"discount_amount":{"type":"number","nullable":true,"description":"The discount the campaign grants.","example":10000}}}},"payments":{"type":"array","description":"Payments. Empty when unpaid or refunded.","items":{"type":"object","required":["id","type","wallet_id","amount","paid_at"],"properties":{"id":{"type":"string","format":"uuid","description":"The payment's id.","example":"3c4d5e6f-7a8b-4c9d-8e1f-2a3b4c5d6e7f"},"type":{"type":"string","enum":["wallet","qris_yukk","qris_midtrans"],"description":"`wallet` (cash, transfer, EDC) or QRIS.","example":"wallet"},"wallet_id":{"type":"string","format":"uuid","nullable":true,"description":"The wallet the money went into, see `GET /wallets`. Null for QRIS.","example":"0d1e2f3a-4b5c-4d6e-8f8a-9b0c1d2e3f4a"},"amount":{"type":"number","example":35520},"paid_at":{"type":"integer","description":"When the payment was made.","example":1790000000}}}},"subtotal":{"type":"number","description":"The items' total after discounts, before extra charges, shipping and tax.","example":32000},"grand_total":{"type":"number","description":"What the buyer owes in all.","example":35520},"paid_amount":{"type":"number","description":"The total of `payments`.","example":35520},"payment_status":{"type":"string","enum":["unpaid","partially_paid","paid"],"description":"Compares `paid_amount` with `grand_total`.","example":"paid"},"sales_return_ids":{"type":"array","description":"Returns and refunds of this sale.","items":{"type":"string","format":"uuid"},"example":["7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d"]}}},"SalesReturnChangeList":{"type":"object","required":["sales_returns","deleted_sales_return_ids","next_since","has_more"],"properties":{"sales_returns":{"type":"array","description":"Oldest change first.","items":{"$ref":"#/components/schemas/SalesReturn"}},"deleted_sales_return_ids":{"type":"array","description":"The returns deleted after `since`. Remove them on your side.","items":{"type":"string","format":"uuid"},"example":["1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e"]},"next_since":{"type":"integer","description":"The cursor to send as `since` next time.","example":87},"has_more":{"type":"boolean","description":"Whether another page is waiting right now. Keep paging while `true`.","example":false}}},"SalesReturn":{"type":"object","description":"A return or refund. A partial return lists only what came back.","required":["id","sales_id","outlet_id","returned_at","returned_by","items","additional_fields","tax_amount","refund_payments","refunded_amount"],"properties":{"id":{"type":"string","format":"uuid","description":"The return's Simplus id.","example":"7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d"},"sales_id":{"type":"string","format":"uuid","nullable":true,"description":"The original sale.","example":"6f1c1d2e-3b4a-4c5d-8e9f-0a1b2c3d4e5f"},"outlet_id":{"type":"string","format":"uuid","example":"2a3b4c5d-6e7f-4a8b-9c0d-1e2f3a4b5c6d"},"returned_at":{"type":"integer","description":"When the return was made.","example":1790003600},"returned_by":{"type":"object","nullable":true,"description":"Who recorded the return, if recorded.","required":["id","name"],"properties":{"id":{"type":"string","format":"uuid","example":"8b9c0d1e-2f3a-4b4c-9d5e-6f7a8b9c0d1e"},"name":{"type":"string","nullable":true,"description":"Null if the account no longer exists.","example":"Budi"}}},"items":{"type":"array","description":"What came back, and how many of each.","items":{"type":"object","required":["product_id","product_type","name","unit","quantity","unit_price","discount_per_qty","tax_rate","subtotal"],"properties":{"product_id":{"type":"string","format":"uuid","example":"9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a"},"product_type":{"type":"string","enum":["variant","bundle"],"example":"variant"},"name":{"type":"string","nullable":true,"description":"The product's current name. Null if the product is gone.","example":"Kopi Susu Gula Aren"},"unit":{"type":"string","nullable":true,"example":"pcs"},"quantity":{"type":"number","description":"The quantity returned.","example":1},"unit_price":{"type":"number","example":18000},"discount_per_qty":{"type":"number","example":2000},"tax_rate":{"type":"number","example":11},"subtotal":{"type":"number","description":"Line total after discount.","example":16000}}}},"additional_fields":{"type":"array","description":"Extra charges given back.","items":{"type":"object","required":["label","amount"],"properties":{"label":{"type":"string","example":"Biaya Layanan"},"amount":{"type":"number","example":2000}}}},"tax_amount":{"type":"number","description":"The tax given back.","example":1760},"refund_payments":{"type":"array","description":"Money paid back, per wallet.","items":{"type":"object","required":["wallet_id","amount"],"properties":{"wallet_id":{"type":"string","format":"uuid","example":"0d1e2f3a-4b5c-4d6e-8f8a-9b0c1d2e3f4a"},"amount":{"type":"number","example":17760}}}},"refunded_amount":{"type":"number","description":"The total of `refund_payments`.","example":17760}}},"CustomerChangeList":{"type":"object","required":["customers","deleted_customer_ids","next_since","has_more"],"properties":{"customers":{"type":"array","description":"Oldest change first.","items":{"$ref":"#/components/schemas/Customer"}},"deleted_customer_ids":{"type":"array","description":"The customers deleted after `since`. Remove them on your side.","items":{"type":"string","format":"uuid"},"example":["2c3d4e5f-6a7b-4c8d-9e0f-1a2b3c4d5e6f"]},"next_since":{"type":"integer","description":"The cursor to send as `since` next time.","example":3051},"has_more":{"type":"boolean","description":"Whether another page is waiting right now. Keep paging while `true`.","example":false}}},"Customer":{"type":"object","required":["id","name","phone","member_code","email","whatsapp_number","group_id","joined_at","point_amount","transaction_count","first_transaction_date","last_transaction_date"],"properties":{"id":{"type":"string","format":"uuid","description":"The customer's Simplus id, the `customer.id` on a sale.","example":"4d5e6f7a-8b9c-4d0e-8f2a-3b4c5d6e7f8a"},"name":{"type":"string","example":"Siti Rahma"},"phone":{"type":"string","example":"081234567890"},"member_code":{"type":"string","example":"MBR-0042"},"email":{"type":"string","nullable":true,"example":"siti@example.com"},"whatsapp_number":{"type":"string","nullable":true,"example":"081234567890"},"group_id":{"type":"string","format":"uuid","nullable":true,"description":"The customer group they belong to, if any.","example":"3e4f5a6b-7c8d-4e9f-8a1b-2c3d4e5f6a7b"},"joined_at":{"type":"integer","description":"When they became a member.","example":1780000000},"point_amount":{"type":"integer","description":"Their current loyalty points.","example":120},"transaction_count":{"type":"integer","description":"How many sales they have made.","example":14},"first_transaction_date":{"type":"integer","nullable":true,"description":"When their first sale was made, or null if none.","example":1780000500},"last_transaction_date":{"type":"integer","nullable":true,"description":"When their latest sale was made, or null if none.","example":1790000000}}},"WalletList":{"type":"object","required":["wallets"],"properties":{"wallets":{"type":"array","description":"All of the business's wallets, or the outlet's for an outlet-scoped key.","items":{"$ref":"#/components/schemas/Wallet"}}}},"Wallet":{"type":"object","required":["id","outlet_id","name","category"],"properties":{"id":{"type":"string","format":"uuid","description":"The `wallet_id` on payments and refunds.","example":"0d1e2f3a-4b5c-4d6e-8f8a-9b0c1d2e3f4a"},"outlet_id":{"type":"string","format":"uuid","example":"2a3b4c5d-6e7f-4a8b-9c0d-1e2f3a4b5c6d"},"name":{"type":"string","example":"Kas Tunai"},"category":{"type":"string","enum":["rekening","fisik","ecommerce","emoney","edc","kasir","other"],"description":"Bank account, cash, e-commerce, e-money, EDC, cashier drawer or other.","example":"fisik"}}},"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"}}}}}}}