openapi: 3.0.3 info: title: Kartustok Public API version: v1 description: | Public read-only API per company for inventory integration. All requests use the company frontend URL and Bearer token authentication. Current product language uses "Warehouse", while the technical contract still uses /locators and locator_id for compatibility with existing clients. servers: - url: https://your-subdomain.kartustok.com/public/v1 security: - bearerAuth: [] tags: - name: Meta - name: Items - name: Stock - name: Master Data paths: /health: get: tags: [Meta] summary: Health check description: Requires `meta.read`. Use it to verify the company domain, token, and public API route. responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/HealthResponse' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/InvalidUrl' '429': $ref: '#/components/responses/TooManyRequests' /meta/company: get: tags: [Meta] summary: Get company metadata description: Requires `meta.read`. Returns lightweight company metadata for the active company subdomain. responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/CompanyResponse' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/InvalidUrl' '429': $ref: '#/components/responses/TooManyRequests' /items: get: tags: [Items] summary: List items description: Requires `item.read`. Item list supports pagination, search, active-status filter, and category filter. parameters: - $ref: '#/components/parameters/Page' - in: query name: per_page schema: type: integer minimum: 1 maximum: 100 default: 20 description: Page size for item list. Default is 20. - in: query name: q schema: type: string - in: query name: is_active schema: type: integer enum: [0, 1] - in: query name: category_id schema: type: string description: Opaque public ID of the item category. responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/ItemListResponse' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '429': $ref: '#/components/responses/TooManyRequests' /items/{id}: get: tags: [Items] summary: Get item detail description: Requires `item.read`. The path parameter uses the public opaque item ID. parameters: - in: path name: id required: true schema: type: string responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/ItemDetailResponse' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/TooManyRequests' /item-categories: get: tags: [Master Data] summary: List item categories description: Requires `category.read`. Returns all matching item categories without pagination. parameters: - in: query name: is_active schema: type: integer enum: [0, 1] responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/CategoryListResponse' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '429': $ref: '#/components/responses/TooManyRequests' /locators: get: tags: [Master Data] summary: List warehouses description: Requires `locator.read`. This endpoint returns warehouse master data even though the technical path remains `/locators`. parameters: - in: query name: is_active schema: type: integer enum: [0, 1] responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/LocatorListResponse' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '429': $ref: '#/components/responses/TooManyRequests' /stock/summary: get: tags: [Stock] summary: Get stock summary description: Requires `stock.read`. Use this endpoint for stock balance snapshots by warehouse and item. parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/PerPage' - $ref: '#/components/parameters/DateFrom' - $ref: '#/components/parameters/DateTo' - in: query name: locator_id schema: type: string description: Single warehouse opaque ID or comma-separated warehouse opaque IDs. Parameter name remains `locator_id` for compatibility. - in: query name: item_id schema: type: string description: Single item opaque ID or comma-separated item opaque IDs. - in: query name: category_id schema: type: string description: Single item-category opaque ID or comma-separated opaque IDs. - in: query name: sort_by schema: type: string enum: [item_name, item_code] - in: query name: show_only_the_mutations_on_the_selected_date schema: type: integer enum: [0, 1] - in: query name: hiding_out_of_stock schema: type: integer enum: [0, 1] - in: query name: hide_voided_transaction schema: type: integer enum: [0, 1] - in: query name: show_inactive_product schema: type: integer enum: [0, 1] responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/StockSummaryResponse' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '429': $ref: '#/components/responses/TooManyRequests' /stock/detail: get: tags: [Stock] summary: Get stock detail description: Requires `stock.read`. Use this endpoint for movement-level audit inside one warehouse. parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/PerPage' - $ref: '#/components/parameters/DateFrom' - $ref: '#/components/parameters/DateTo' - in: query name: locator_id required: true schema: type: string description: Required warehouse opaque ID. Parameter name remains `locator_id` for compatibility. - in: query name: item_id schema: type: string description: Optional item opaque ID to narrow the report. - in: query name: transaction_type schema: type: string description: Single transaction type or comma-separated transaction types. - in: query name: hide_voided_transaction schema: type: integer enum: [0, 1] responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/StockDetailResponse' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '429': $ref: '#/components/responses/TooManyRequests' components: securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: API Token parameters: Page: in: query name: page schema: type: integer minimum: 1 default: 1 PerPage: in: query name: per_page schema: type: integer minimum: 1 maximum: 100 default: 50 DateFrom: in: query name: date_from schema: type: string format: date DateTo: in: query name: date_to schema: type: string format: date responses: Unauthorized: description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: status: error message: Unauthorized Forbidden: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: status: error message: Forbidden InvalidUrl: description: Invalid company URL content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: status: error message: Invalid URL TooManyRequests: description: Too Many Requests content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: status: error message: Too Many Requests NotFound: description: Not Found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' schemas: ErrorResponse: type: object properties: status: type: string example: error message: type: string required: [status, message] Pagination: type: object properties: page: type: integer per_page: type: integer total: type: integer required: [page, per_page, total] CustomField: type: object properties: id: type: string name: type: string type: type: string options: type: array items: {} is_active: type: integer mandatory: type: integer value: {} Category: type: object properties: id: type: string name: type: string description: type: string nullable: true fields: type: array items: $ref: '#/components/schemas/CustomField' is_active: type: integer Locator: type: object description: Warehouse object. The schema name remains `Locator` for technical compatibility. properties: id: type: string name: type: string description: type: string nullable: true is_active: type: integer Uom: type: object properties: id: type: string code: type: string name: type: string description: type: string nullable: true precision: type: integer is_active: type: integer Item: type: object properties: id: type: string code: type: string name: type: string upc_ean: type: string nullable: true description: type: string nullable: true minimum_quantity: type: number is_active: type: integer category: $ref: '#/components/schemas/Category' uom: $ref: '#/components/schemas/Uom' fields: type: array items: $ref: '#/components/schemas/CustomField' category_fields: type: array items: $ref: '#/components/schemas/CustomField' HealthResponse: type: object properties: status: type: string example: success data: type: object properties: ok: type: boolean time: type: string format: date-time required: [ok, time] CompanyResponse: type: object properties: status: type: string data: type: object properties: id: type: string name: type: string subdomain: type: string timezone: type: string language: type: string ItemListResponse: type: object properties: status: type: string data: type: object properties: items: type: array items: $ref: '#/components/schemas/Item' count: type: integer total: type: integer pagination: $ref: '#/components/schemas/Pagination' ItemDetailResponse: type: object properties: status: type: string data: $ref: '#/components/schemas/Item' CategoryListResponse: type: object properties: status: type: string data: type: object properties: items: type: array items: $ref: '#/components/schemas/Category' count: type: integer total: type: integer LocatorListResponse: type: object properties: status: type: string data: type: object properties: items: type: array items: $ref: '#/components/schemas/Locator' count: type: integer total: type: integer StockSummaryRow: type: object properties: locator: $ref: '#/components/schemas/Locator' item: $ref: '#/components/schemas/Item' stock: type: object properties: beginning: type: number in: type: number out: type: number ending: type: number precision: type: integer StockSummaryResponse: type: object properties: status: type: string data: type: object properties: items: type: array items: $ref: '#/components/schemas/StockSummaryRow' count: type: integer total: type: integer filters: type: object properties: date_from: type: string format: date date_to: type: string format: date pagination: $ref: '#/components/schemas/Pagination' StockDetailRow: type: object properties: id: type: string transaction_date: type: string format: date document_number: type: string reference: type: string nullable: true transaction_type: type: string transaction_category: type: string created_by: type: string doc_status: type: integer description: type: string nullable: true document_description: type: string nullable: true locator: $ref: '#/components/schemas/Locator' item: $ref: '#/components/schemas/Item' stock_in: type: number nullable: true stock_out: type: number nullable: true StockDetailResponse: type: object properties: status: type: string data: type: object properties: header: type: object properties: locator_name: type: string nullable: true item_code: type: string nullable: true item_name: type: string nullable: true uom_name: type: string nullable: true uom_precision: type: integer beginning_balance: type: number ending_balance: type: number item: nullable: true oneOf: - $ref: '#/components/schemas/Item' report: type: array items: $ref: '#/components/schemas/StockDetailRow' count: type: integer total: type: integer pagination: $ref: '#/components/schemas/Pagination'