POS Integration API
A Cloudflare Workers API for managing pharmacy product inventory with authentication and batch processing capabilities
Base URL
https://positec-dev.curly-mode-08ce.workers.dev
Authentication
All API requests (except health check) require authentication using API keys and HMAC SHA-256 signature verification.
Headers Required
X-API-Key: {your_public_key}
X-Signature: {hmac_sha256_signature}
X-Timestamp: {unix_timestamp}
Content-Type: application/json
Content-Length: {request_body_length}HMAC Signature
Generate HMAC SHA-256 signature using your secret key and the payload
Example payload for signing:
{"pharmacy_id":"123", "medaki_pharmacy_id":"med123", "action":"create","products":[...]}Endpoints
GET /health
Health check endpoint that verifies database connectivity.
Authentication: Not required
Response:
{
"status": 200,
"success": true,
"message": "ok",
"data": {
"database": "healthy",
"timestamp": "2023-12-01T10:00:00.000Z"
},
"elapsed_ms": 45
}Error Response (503):
{
"status": 503,
"success": false,
"message": "Database unhealthy",
"error": "Connection timeout",
"elapsed_ms": 5000
}GET /
Retrieve products with pagination and filtering.
Authentication: Required
Query Parameters:
pharmacy_id(required): Pharmacy identifiergtin(optional): Product GTIN for specific product lookupskip(optional): Number of records to skip for pagination (default: 0)
Example Request:
GET /?pharmacy_id=123>in=1234567890123&skip=0Success Response (200):
{
"status": 200,
"success": true,
"data": [
{
"ref_id": "550e8400-e29b-41d4-a716-446655440000",
"old_gtin": "1234567890123",
"gtin": "1234567890123",
"brand": "ExampleBrand",
"old_name": "Old Product Name",
"name": "Product Name",
"description": "Product description",
"category": "Health",
"image_url": "https://example.com/image.jpg",
"stock": 100,
"price": 29.99,
"sale_price": 24.99,
"distributor": "Distributor Name",
}
],
"pagination": {
"count": 1,
"has_more": false,
"cursor": "next_page_items_offset"
},
"elapsed_ms": 145
}Not Found Response (404):
{
"status": 404,
"success": false,
"error": "Product with GTIN '1234567890123' not found for pharmacy with ID '123'",
"elapsed_ms": 89
}POST /
Create or update products in batches.
Authentication: Required Content-Type: application/json
Request Body:
{
"pharmacy_id": "123",
"medaki_pharmacy_id": "med123",
"action": "create",
"products": [
{
"old_gtin": "1234567890123",
"gtin": "1234567890123",
"brand": "ExampleBrand",
"old_name": "Old Product Name",
"name": "Product Name",
"description": "Product description",
"category": "Health",
"image_url": "https://example.com/image.jpg",
"stock": 100,
"price": 29.99,
"sale_price": 24.99,
"distributor": "Distributor Name",
}
]
}Field Descriptions:
pharmacy_id: Pharmacy identifiermedaki_pharmacy_id: MedaKi internal pharmacy IDaction: Either "create" or "update"products: Array of product objects
Product Object Fields:
old_gtin(required): Original GTINgtin(required): Current GTINname(required): Product namestock(required): Stock quantityprice(required): Product pricesale_price(optional): Sale pricebrand(optional): Product brandold_name(optional): Previous product namedescription(optional): Product descriptioncategory(optional): Product categoryimage_url(optional): Product image URLdistributor(optional): Distributor name
Success Response (200):
{
"status": 200,
"success": true,
"data": {
"message": "Successfully created product(s)",
"elapsed_ms": 1250,
"processed_items": 1,
"chunks_processed": 1
}
}Error Responses
Authentication Errors
401 Unauthorized:
{
"status": 401,
"success": false,
"error": "Invalid API key"
}403 Forbidden:
{
"status": 403,
"success": false,
"error": "Invalid signature"
}Validation Errors
400 Bad Request:
{
"status": 400,
"success": false,
"error": "Duplicate GTINs found in payload: 1234567890123, 9876543210987"
}413 Request Too Large:
{
"status": 413,
"message": "Request too large. Maximum size allowed: 5242880 bytes (5 MB)",
"provided_size": 6000000,
"max_size": 5242880
}Timeout Errors
408 Request Timeout:
{
"status": 408,
"success": false,
"error": "Request timed out during database operation",
"elapsed_ms": 30000,
"timeout_ms": 30000
}Server Errors
500 Internal Server Error:
{
"status": 500,
"success": false,
"error": "Internal server error",
"elapsed_ms": 123
}503 Service Unavailable:
{
"status": 503,
"success": false,
"message": "Database is currently unavailable",
"error": "Connection failed",
"elapsed_ms": 5000
}Rate Limits & Constraints
Request Size Limit: 5 MB
Batch Size: Processed in chunks of 100-250 products
Page Size: 1000 products per GET request
Request Timeout: 30 seconds total
Authentication Timeout: 5 seconds
Database Operation Timeout: Variable based on operation
Data Models
Product
interface Product {
ref_id: string;
old_gtin: string;
gtin: string;
brand?: string;
old_name?: string;
name: string;
description?: string;
category?: string;
image_url?: string;
stock: number;
price: number;
sale_price?: number;
provider: "positec" | "autostar" | "maplewave";
distributor?: string;
}Code Examples
JavaScript/Node.js Authentication Example
const crypto = require('crypto');
async function sha256Hash(data, key) {
const encoder = new TextEncoder();
const encodedData = encoder.encode(data);
const encodedKey = encoder.encode(key);
const cryptoKey = await crypto.subtle.importKey('raw', encodedKey, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
const signature = await crypto.subtle.sign('HMAC', cryptoKey, encodedData);
return Array.from(new Uint8Array(signature))
.map((byte) => byte.toString(16).padStart(2, '0'))
.join('');
}
const timestamp = Math.floor(Date.now() / 1000);
const body = JSON.stringify({
pharmacy_id: "123",
medaki_pharmacy_id: "med123",
action: "create",
products: [/* product data */]
});
const signature = await sha256Hash(body, secretKey);
const headers = {
'X-API-Key': publicKey,
'X-Signature': signature,
'X-Timestamp': timestamp.toString(),
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(body).toString()
};cURL Example
# Health Check
curl -X GET https://positec-dev.curly-mode-08ce.workers.dev/health
# Get Products
curl -X GET \
"https://positec-dev.curly-mode-08ce.workers.dev/?pharmacy_id=123&skip=0" \
-H "X-API-Key: your_public_key" \
-H "X-Signature: generated_signature" \
-H "X-Timestamp: 1672531200"
# Create Products
curl -X POST \
https://positec-dev.curly-mode-08ce.workers.dev/ \
-H "Content-Type: application/json" \
-H "X-API-Key: your_public_key" \
-H "X-Signature: generated_signature" \
-H "X-Timestamp: 1672531200" \
-d '{
"pharmacy_id": "123",
"medaki_pharmacy_id": "med123",
"action": "create",
"products": [
{
"old_gtin": "1234567890123",
"gtin": "1234567890123",
"name": "Product Name",
"stock": 100,
"price": 29.99,
...
}
]
}'Last updated