LOCURA API
v1.0A unified REST API for integrating with the LOCURA ecosystem. Connect your ERP, WMS, or custom applications to manage clients, inventory forecasting, S&OP planning, dock scheduling, parcel monitoring, and AI-powered document generation.
Hub
16 endpointsIdentity provider, clients, files, API keys, webhooks
https://hub.locura.tech/api/v1/Pronostico
23 endpointsInventory management, ABC/XYZ, demand forecasting
https://pronostico.locura.tech/api/v1/Avisator
16 endpointsDock scheduling, bookings, supplier communication
https://avisator.locura.tech/api/v1/DocMaker
13 endpointsControlled documents, configurable types, templates and review releases
https://docmaker.locura.tech/api/v1/Validator
3 endpointsEvidence-grounded compliance with tenant-scoped product and status reads for ERP, QMS and BI
https://validator.locura.tech/api/v1/Efectiver
16 endpointsWorkforce performance & bonus, competency matrix, EU Pay Transparency (2023/970) foundation
https://efectiver.locura.tech/api/v1/Consenso
13 endpointsS&OP planning: demand consensus on product families, economics & budget targets, financial reconciliation, cycle freeze
https://consenso.locura.tech/api/v1/Tracker
11 endpointsUPS and DHL parcel monitoring, exception control, imports and ERP status writeback
https://tracker.locura.tech/api/v1/Modeler
API planned3D warehouse design, digital twins and autonomous layout generation; public REST API in development
https://modeler.locura.tech/api/v1/Base URLs
Hub: https://hub.locura.tech/api/v1
Pronostico: https://pronostico.locura.tech/api/v1
Avisator: https://avisator.locura.tech/api/v1
DocMaker: https://docmaker.locura.tech/api/v1
Validator: https://validator.locura.tech/api/v1
Efectiver: https://efectiver.locura.tech/api/v1
Consenso: https://consenso.locura.tech/api/v1
Tracker: https://tracker.locura.tech/api/v1
Live service status and incident history: status.locura.tech
Authentication
All API requests require a Bearer token in the Authorization header. API keys are managed through the Hub application.
API Key Format
| Prefix | Type | Description |
|---|---|---|
| lk_live_* | Live Secret | Full access to production data. Keep server-side only. |
| lk_test_* | Test Secret | Sandbox environment. Safe for development and testing. |
| lk_pub_* | Publishable | Read-only access. Safe for client-side use. |
Getting Your API Key
- Log into Hub at
hub.locura.tech - Navigate to Settings → API → Klucze API
- Click "Create new key", select scopes, and copy the key
- Store the key securely -- it will not be shown again
Security: API keys are stored as SHA-256 hashes. Once created, the full key cannot be retrieved. If you lose your key, revoke it and create a new one.
Usage
Include the key as a Bearer token in every request:
curl -X GET "https://hub.locura.tech/api/v1/clients" \ -H "Authorization: Bearer lk_live_abc123def456ghi789jkl012mno345"
Rate Limiting
API requests are rate-limited per API key. The limits depend on your subscription tier.
| Tier | Requests / min | Burst |
|---|---|---|
| Free | 60 | 10 requests |
| Pro | 300 | 50 requests |
| Enterprise | 1,000 | 100 requests |
Response Headers
Every response includes rate limit information:
| Header | Description |
|---|---|
| X-RateLimit-Limit | Maximum requests per window |
| X-RateLimit-Remaining | Remaining requests in current window |
| X-RateLimit-Reset | Unix timestamp when the window resets |
429 Too Many Requests
{ "type": "https://api.locura.tech/errors/rate-limit-exceeded", "title": "Rate limit exceeded", "status": 429, "detail": "You have exceeded 60 requests per minute. Please retry after 23 seconds.", "instance": "/api/v1/clients", "request_id": "req_a1b2c3d4e5f6", "retry_after": 23 }
Brute Force Protection
After 5 consecutive failed authentication attempts, an exponential delay is applied. The delay doubles with each additional failure, starting at 1 second up to a maximum of 60 seconds.
Error Handling
All errors follow the RFC 7807 Problem Details format, providing consistent, machine-readable error responses.
Error Response Structure
{ "type": "https://api.locura.tech/errors/validation-error", "title": "Validation Error", "status": 422, "detail": "Field 'email' must be a valid email address.", "instance": "/api/v1/suppliers", "request_id": "req_x7y8z9a0b1c2" }
HTTP Status Codes
| Status | Title | Description |
|---|---|---|
| 400 | Bad Request | The request body or parameters are malformed. |
| 401 | Unauthorized | Missing or invalid API key. |
| 403 | Forbidden | API key lacks the required scope for this operation. |
| 404 | Not Found | The requested resource does not exist. |
| 409 | Conflict | Resource already exists or state conflict (e.g., double booking). |
| 422 | Unprocessable Entity | Validation error -- the request body failed schema validation. |
| 429 | Too Many Requests | Rate limit exceeded. Retry after the time indicated in the response. |
| 500 | Internal Server Error | Unexpected server error. Contact support with the request_id. |
Pagination
All list endpoints support offset-based pagination with the following query parameters.
| Parameter | Default | Description |
|---|---|---|
| page | 1 | Page number (1-based) |
| per_page | 50 | Items per page (max 100) |
Example Request
curl "https://hub.locura.tech/api/v1/clients?page=2&per_page=25" \ -H "Authorization: Bearer lk_live_abc123def456"
Response Format
{ "data": [ { "id": "cli_abc123", "name": "Acme Corp", "nip": "1234567890" } ], "pagination": { "page": 2, "per_page": 25, "total": 87 }, "links": { "next": "/api/v1/clients?page=3&per_page=25", "prev": "/api/v1/clients?page=1&per_page=25" } }
Hub API
The Hub is the central identity provider for the LOCURA ecosystem. It manages clients, files stored in Cloudflare R2, API keys, webhooks, usage tracking, and GDPR compliance.
Base URL: https://hub.locura.tech/api/v1
Health Check
Clients
Files (R2 Storage)
API Keys
Webhooks
Usage & Audit
GDPR Compliance
Sandbox
Changelog
Pronostico API
Pronostico is the inventory management and demand forecasting engine. Push your sales, stock, and purchasing data, then run AI-powered analysis to get ABC/XYZ classifications, demand forecasts, and purchase order recommendations.
Base URL: https://pronostico.locura.tech/api/v1
Health Check
Data Push & Read
Push your operational data to Pronostico before running analysis. For datasets with 5,000 rows or fewer, processing is synchronous. Larger datasets return an async job ID. Each POST endpoint has a paired GET for reading the deduped rows back out (useful for ERP reconciliation).
Analysis
Results
Suppliers
Customers
Customer rankings derived from sales data: revenue share, order/document counts, and an automatic classification (top / regular / sporadic) based on Pareto contribution.
SKU Detail
Single-call snapshot for a SKU: classification, forecast, recommendation, weekly demand history, recent stock snapshots, and the customer breakdown — same data the dashboard SKU detail page renders.
Avisator API
Avisator handles dock scheduling and supplier communication. Manage warehouse locations, docks, time slots, and booking reservations for inbound and outbound deliveries.
Base URL: https://avisator.locura.tech/api/v1
Health Check
Locations
Bookings
Suppliers
Vehicles
Available Slots
Dock Map
DocMaker API
DocMaker is the controlled document generation platform. It produces analyses, audits, offers, contracts, presentations, articles, bonus systems, Gantt charts, transcriptions, and configurable PDF/DOCX document types. Published definitions and templates are immutable and every generated document retains both version pins. The API exposes document, governance, template, type, and job metadata without prompts or internal storage paths.
Base URL: https://docmaker.locura.tech/api/v1
Health Check
Documents
Configurable Document Types
Generation Jobs
Validator API
Validator is a universal, evidence-grounded document-compliance engine. It indexes a corpus of source documents (standards, regulations, internal procedures) and provides citation-grounded answers with sentence-level evidence to specific PDF page numbers. Multi-hop retrieval splits complex questions into sub-aspects and retrieves chunks per sub-question separately. It is currently trained on the power-tools domain (PN-EN/IEC standards, CE marking) and applies to any document-heavy field — legal, pharma, medical devices, finance — by loading that domain's source corpus.
Base URL: https://validator.locura.tech/api/v1
The public contract exposes two read-only, tenant-scoped projections for ERP, QMS and BI integrations. Create the API key in LOCURA Hub and grant only the required Validator scope. Notes, storage paths, run IDs and internal record identifiers are intentionally excluded. The compliance chat, library, audits and standards-diff remain session-authenticated web application workflows.
Health Check
Products
Compliance Status
Efectiver API
Efectiver is a multi-tenant workforce-performance and competency platform. It ingests performance events from external source systems, computes per-worker productivity, norm fulfilment and bonus analytics, and maintains a competency matrix with bus-factor risk detection — the data foundation for EU Pay Transparency (Directive 2023/970) reporting. Tenant isolation is enforced by PostgreSQL FORCE Row Level Security.
Base URL: https://efectiver.locura.tech/api/v1
Authentication differs from the rest of the LOCURA platform. Tenant provisioning uses a platform-operator admin key (x-efectiver-admin-key); ingest uses a per-source API key (x-efectiver-key); analytics endpoints use the efectiver_session cookie set by login, or an Authorization: Bearer token.
Onboarding
Request fields: tenantName (string, required, unique — 409 if taken), industry (string, required), adminEmail (valid email, required), adminPassword (string, required, min 8 chars), seedFramework (boolean, optional — seeds competency framework tasks), seedEngineDefaults (boolean, optional — seeds engine configuration defaults).
Status codes: 201 created · 400 invalid body (zod) · 401 missing/wrong admin key · 409 tenant name already exists · 500 unexpected server error.
Authentication
Sets efectiver_session cookie (httpOnly, SameSite=Lax, Secure in production, Max-Age 7d). User lookup uses the SECURITY DEFINER function lookup_user_by_email (controlled RLS bypass for pre-auth lookup).
Status codes: 200 OK · 400 missing/invalid body · 401 wrong credentials or user not found · 429 too many failed attempts (10 per 5 min per IP+email).
Ingest
The request body is a JSON array of performance event objects (source-specific schema). Maximum 50 000 events per request.
Status codes: 200 processed (see report) · 400 invalid JSON or row-level validation errors · 401 missing/invalid x-efectiver-key · 413payload exceeds 50 000 events.
Performance
Response fields: workers (WorkerResult[] — per-worker totals), heatmap (DailyCell[] — per-worker per-day earnedHours + normPct), dailyKpi (DailyKpi[] — site-level lines/workers/avgNormPct per day), trend (TrendPoint[] — avgNormPct + totalBonus per day), mdm (MdmResult | null — month-over-month, only when prevFrom + prevTo supplied). Session resolved to (tenantId, userId) via SECURITY DEFINER lookup_session.
Status codes: 200 OK · 400 missing/invalid from/to · 401 missing or expired session · 500 internal error.
Competency
Response fields: byCompetency (CompetencyCoverage[] — per-competency metrics), busFactorRisks(competency codes with peopleCount ≤ 1), uncoveredCompetencies (competency codes with peopleCount == 0), heatmap (HeatmapCell[] — employee × competency tasksHeld/tasksTotal), totals (competencies/employees/tasks counts). Status codes: 200 OK · 401 missing/expired session · 500 internal error.
AI gate: returns 503 unless EFECTIVER_AI_ENABLED=true. Enabling requires explicit cost approval and a configured provider. Status codes: 200 OK · 400 missing/invalid context · 401 not authenticated · 403 forbidden role (requires HR or Manager) · 503 AI provider not enabled.
Status codes: 200 OK · 401 not authenticated · 403 forbidden role (requires HR or Manager) · 404 suggestion not found (or belongs to another tenant — fail-closed) · 409 suggestion already approved or rejected (double-approve guard) · 500 internal error.
Clients
Status codes: 200/201 OK · 401 not authenticated · 403 GET non-allowed role / POST non-HR · 409 duplicate slug · 422 invalid name or empty derived slug.
Overhead Costs
Categories (ASCII keys): magazyn · media · transport · materialy. Status codes: 200 OK · 400 super-admin referencing a non-existent department · 401 not authenticated · 403 non-HR write or dept-scoped HR targeting another department · 404 id not in the caller department scope · 422 invalid category, periodMonth or amount.
Cost & OTIF
Ingest: rows posted to POST /api/v1/ingest/orders may include an optional client (name or slug) — the order is stamped with the resolved or created client_id (idempotent on the tenant slug). Status codes: 200 OK · 401 not authenticated · 403 role Pracownik.
Compliance
Status codes: 200 OK · 401 not authenticated · 403 role HR or Audytor required · 500 server error
Status codes: 201 created · 400 invalid JSON, missing path or domain validation · 401 not authenticated · 403 role HR required · 500 server error
Status codes: 200 OK · 400 invalid JSON, missing path.id or domain validation · 401 not authenticated · 403 role HR required · 500 server error
Status codes: 200 OK · 400 missing id · 401 not authenticated · 403 role HR required · 500 server error
Status codes: 200 OK · 200 no pay data (status payload) · 401 not authenticated · 500 server error
Status codes: 200 OK (XLSX file) · 401 not authenticated · 403 role HR or Audytor required · 500 server error
Status codes: 200 OK · 401 not authenticated · 403 role HR or Audytor required · 500 server error
Status codes: 201 created · 400 invalid JSON, missing band or domain validation · 401 not authenticated · 403 role HR required · 500 server error
Status codes: 200 OK · 400 invalid JSON, missing band.id or domain validation · 401 not authenticated · 403 role HR required · 500 server error
Status codes: 200 OK · 400 missing id · 401 not authenticated · 403 role HR required · 500 server error
Status codes: 200 OK · 401 not authenticated · 403 role HR or Audytor required · 500 server error
Configuration
Status codes: 200 OK · 401 missing or invalid session · 500 internal error
Status codes: 200 OK · 400 invalid JSON body · 401 missing or invalid session · 500 internal error
Cost Simulation
Status codes: 200 OK · 400 missing or invalid addedOrders · 401 missing or invalid session · 403 role Pracownik · 500 internal error
Departments
Status codes: 200 OK · 401 missing or invalid session · 403 not tenant super-admin
Status codes: 201 Created · 400 invalid JSON, validation error or duplicate slug · 401 missing or invalid session · 403 not tenant super-admin · 500 server error
Status codes: 200 OK · 400 invalid JSON or validation error · 401 missing or invalid session · 403 not tenant super-admin · 500 server error
Employee Portfolio
Status codes: 200 OK · 401 missing or invalid session · 403 foreign ref for role Pracownik · 404 employee not found · 500 internal error
Status codes: 200 OK (application/pdf) · 401 missing or invalid session · 403 foreign ref for role Pracownik · 404 employee not found · 500 PDF generation error
Errors & Anomalies
Status codes: 200 OK · 401 missing or invalid session · 500 internal error
Status codes: 201 created · 400 invalid JSON or validation error (employeeId/occurredOn/description/amountPln/attachmentUri) · 401 missing or invalid session · 500 internal error
Status codes: 200 OK · 400 invalid JSON or validation error (orderId) · 401 missing or invalid session · 500 internal error
Status codes: 200 OK · 401 missing or invalid session · 500 internal error
Import
Status codes: 200 OK · 401 not authenticated · 500 internal error
Status codes: 200 OK · 400 not multipart or missing file or unreadable file · 401 not authenticated · 413 file too large · 415 unsupported file type
Status codes: 200 OK · 401 not authenticated · 500 internal error
Status codes: 201 Created · 400 invalid JSON or missing name or invalid name · 401 not authenticated · 409 duplicate name · 500 internal error
Status codes: 200 OK · 401 not authenticated · 500 internal error
Status codes: 200 OK · 400 not multipart or missing file or missing mapping or invalid mapping JSON or mapping not object or mapping incomplete or processing failed · 401 not authenticated · 413 file too large or too many rows · 415 unsupported file type
Orders Ingest
Status codes: 200 OK · 400 invalid JSON body or not an array · 401 missing or invalid API key · 413 payload over 50000 rows · 422 unparseable placed_at or shipped_at
Order-Type Cutoffs
Status codes: 200 OK · 401 not authenticated or invalid session · 500 server error
Status codes: 201 Created · 400 invalid JSON or department does not exist · 401 not authenticated · 403 role not HR or wrong department · 409 cutoff already exists · 422 validation error · 500 server error
Status codes: 200 OK · 400 invalid JSON or no fields to update · 401 not authenticated · 403 role not HR · 422 validation error · 500 server error
Status codes: 200 OK · 401 not authenticated · 403 role not HR · 500 server error
Consenso API
Consenso is the S&OP planning layer of the LOCURA ecosystem. It consumes forecasts from Pronostico, rolls SKUs up to product families, and lets planners record demand consensus, planning economics and budget targets, then freeze a cycle with a full financial reconciliation snapshot.
Base URL: https://consenso.locura.tech/api/v1
Authentication: Consenso endpoints (except /health) are authenticated with the signed-in user session (LOCURA Hub SSO) and are scoped to the user's company. Bearer API-key access is on the roadmap; until then, integrate on the Pronostico side (GET /api/v1/forecasts) and use Consenso through the web UI or an authenticated session.
Health Check
Planning Cycles
Demand Consensus
Economics & Budget
Product Families
Pronostico Connection
Tracker API
Tracker monitors UPS and DHL shipments, normalizes carrier statuses, detects operational exceptions, and synchronizes status changes with stores or ERP systems. API keys are issued in Hub and must include the scope required by each operation.
Base URL: https://tracker.locura.tech/api/v1 | OpenAPI: https://tracker.locura.tech/api/docs.json | Swagger UI: https://tracker.locura.tech/api/docs
Health
Shipments
Imports
ERP & Store Ingest
Signed status callbacks
When an ingested shipment changes status, Tracker sends the JSON payload to the registered callback URL. Verify the lowercase hexadecimal HMAC-SHA256 of the raw request body before parsing it.
X-LOCURA-Event: event typeX-LOCURA-Idempotency-Key: stable delivery key for deduplicationX-LOCURA-Signature: HMAC-SHA256 signature of the raw body
Exceptions
Operations
Modeler
Modeler is the 3D warehouse design studio of the LOCURA ecosystem: interactive layout editing, digital twins with DWG/DXF underlays, autonomous layout generation and comprehensive PDF concept reports.
Public REST API in development. Modeler currently exposes no public /api/v1 endpoints; the application is available at modeler.locura.tech with LOCURA Hub SSO, and project sharing works through PIN-protected public view links generated in the app. Watch the changelog below for the API release.
Webhooks
Webhooks allow your application to receive real-time notifications when events occur in the LOCURA ecosystem. Events are delivered via HTTP POST to your configured endpoint with an HMAC-SHA256 signature for verification.
Available Events
| Event | App | Description |
|---|---|---|
| avisator.booking.created | Avisator | A new booking was created |
| avisator.booking.approved | Avisator | A booking was approved |
| avisator.booking.rejected | Avisator | A booking was rejected |
| avisator.booking.cancelled | Avisator | A booking was cancelled |
| avisator.booking.arrived | Avisator | Vehicle arrived at the dock |
| avisator.booking.completed | Avisator | Booking completed (loading/unloading done) |
| avisator.booking.no_show | Avisator | Vehicle did not show up |
| pronostico.analysis.completed | Pronostico | Analysis job finished processing |
Webhook Payload Format
{ "id": "evt_a1b2c3d4e5", "type": "avisator.booking.created", "timestamp": "2026-03-24T10:00:00.000Z", "data": { "booking_id": "bk_e5f6g7h8", "location_id": "loc_a1b2c3d4", "dock_id": "dock_x1y2z3", "supplier_id": "sup_m1n2o3p4", "date": "2026-03-25", "start_time": "08:00" } }
HMAC-SHA256 Signature Verification
Each webhook delivery includes an X-Locura-Signature header. Verify it by computing the HMAC-SHA256 of the raw request body using your webhook secret.
Node.js
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload, 'utf8')
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// In your Express handler:
app.post('/webhooks/locura', (req, res) => {
const signature = req.headers['x-locura-signature'];
const isValid = verifyWebhookSignature(
JSON.stringify(req.body),
signature,
process.env.LOCURA_WEBHOOK_SECRET
);
if (!isValid) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Process the event
const event = req.body;
console.log('Received event:', event.type);
res.status(200).json({ received: true });
});Python
import hmac
import hashlib
import os
from flask import Flask, request, jsonify
app = Flask(__name__)
def verify_webhook_signature(payload, signature, secret):
expected = hmac.new(
secret.encode('utf-8'),
payload.encode('utf-8'),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)
@app.route('/webhooks/locura', methods=['POST'])
def handle_webhook():
signature = request.headers.get('X-Locura-Signature')
is_valid = verify_webhook_signature(
request.get_data(as_text=True),
signature,
os.environ['LOCURA_WEBHOOK_SECRET']
)
if not is_valid:
return jsonify({'error': 'Invalid signature'}), 401
event = request.get_json()
print(f"Received event: {event['type']}")
return jsonify({'received': True}), 200Retry Policy
Failed deliveries (non-2xx response or timeout) are retried up to 6 times with exponential backoff:
| Attempt | Delay |
|---|---|
| 1st retry | 2 minutes |
| 2nd retry | 4 minutes |
| 3rd retry | 8 minutes |
| 4th retry | 16 minutes |
| 5th retry | 32 minutes |
| 6th retry (final) | 64 minutes |
After 6 failed attempts, the webhook is marked as disabled. You can re-enable it through the Hub UI or by deleting and recreating it via the API.
Code Examples
Complete working examples for common integration scenarios across all supported languages.
1. Authenticate and List Clients
curl
# List all clients curl "https://hub.locura.tech/api/v1/clients" \ -H "Authorization: Bearer lk_live_abc123def456ghi789jkl012mno345" # Search for a specific client curl "https://hub.locura.tech/api/v1/clients?search=Acme&per_page=5" \ -H "Authorization: Bearer lk_live_abc123def456ghi789jkl012mno345"
Python
import requests
API_KEY = "lk_live_abc123def456ghi789jkl012mno345"
BASE_URL = "https://hub.locura.tech/api/v1"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
# List clients
response = requests.get(f"{BASE_URL}/clients", headers=headers)
data = response.json()
for client in data["data"]:
print(f"{client['name']} (NIP: {client['nip']})")
print(f"Total: {data['pagination']['total']} clients")JavaScript
const API_KEY = 'lk_live_abc123def456ghi789jkl012mno345';
const BASE_URL = 'https://hub.locura.tech/api/v1';
async function listClients() {
const response = await fetch(`${BASE_URL}/clients`, {
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
}
});
const { data, pagination } = await response.json();
data.forEach(client => {
console.log(`${client.name} (NIP: ${client.nip})`);
});
console.log(`Total: ${pagination.total} clients`);
}
listClients();2. Create a Dock Booking
curl
# Step 1: Check available slots
curl "https://avisator.locura.tech/api/v1/slots?location_id=loc_a1b2c3d4&date=2026-03-25" \
-H "Authorization: Bearer lk_live_abc123def456"
# Step 2: Create the booking
curl -X POST "https://avisator.locura.tech/api/v1/bookings" \
-H "Authorization: Bearer lk_live_abc123def456" \
-H "Content-Type: application/json" \
-d '{
"location_id": "loc_a1b2c3d4",
"dock_id": "dock_x1y2z3",
"supplier_id": "sup_m1n2o3p4",
"vehicle_type_id": "vt_tir",
"date": "2026-03-25",
"start_time": "09:00",
"license_plate": "DW 12345",
"driver_name": "Jan Kowalski",
"cargo_description": "20 pallets of electronics"
}'Python
import requests
API_KEY = "lk_live_abc123def456ghi789jkl012mno345"
BASE_URL = "https://avisator.locura.tech/api/v1"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
# Check available slots
slots = requests.get(
f"{BASE_URL}/slots",
headers=headers,
params={"location_id": "loc_a1b2c3d4", "date": "2026-03-25"}
).json()
# Find first available slot
for dock in slots["data"]:
for slot in dock["slots"]:
if slot["available"]:
print(f"Available: {dock['dock_name']} at {slot['start_time']}")
break
# Create booking
booking = requests.post(
f"{BASE_URL}/bookings",
headers=headers,
json={
"location_id": "loc_a1b2c3d4",
"dock_id": "dock_x1y2z3",
"supplier_id": "sup_m1n2o3p4",
"vehicle_type_id": "vt_tir",
"date": "2026-03-25",
"start_time": "09:00",
"license_plate": "DW 12345",
"driver_name": "Jan Kowalski",
"cargo_description": "20 pallets of electronics"
}
).json()
print(f"Booking created: {booking['data']['id']}")JavaScript
const API_KEY = 'lk_live_abc123def456ghi789jkl012mno345';
const BASE_URL = 'https://avisator.locura.tech/api/v1';
const headers = {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
};
async function createBooking() {
// Check available slots
const slotsRes = await fetch(
`${BASE_URL}/slots?location_id=loc_a1b2c3d4&date=2026-03-25`,
{ headers }
);
const slots = await slotsRes.json();
// Create the booking
const bookingRes = await fetch(`${BASE_URL}/bookings`, {
method: 'POST',
headers,
body: JSON.stringify({
location_id: 'loc_a1b2c3d4',
dock_id: 'dock_x1y2z3',
supplier_id: 'sup_m1n2o3p4',
vehicle_type_id: 'vt_tir',
date: '2026-03-25',
start_time: '09:00',
license_plate: 'DW 12345',
driver_name: 'Jan Kowalski',
cargo_description: '20 pallets of electronics'
})
});
const booking = await bookingRes.json();
console.log(`Booking created: ${booking.data.id}`);
}
createBooking();3. Push Sales Data and Run Analysis
curl
# Step 1: Push sales data
curl -X POST "https://pronostico.locura.tech/api/v1/data/sales" \
-H "Authorization: Bearer lk_live_abc123def456" \
-H "Content-Type: application/json" \
-d '{
"rows": [
{"sku": "SKU-001", "date": "2026-01-15", "quantity": 120, "revenue": 4560.00},
{"sku": "SKU-001", "date": "2026-02-15", "quantity": 135, "revenue": 5130.00},
{"sku": "SKU-002", "date": "2026-01-15", "quantity": 45, "revenue": 1350.00}
]
}'
# Step 2: Start analysis
curl -X POST "https://pronostico.locura.tech/api/v1/analysis/run" \
-H "Authorization: Bearer lk_live_abc123def456" \
-H "Content-Type: application/json" \
-d '{"type": "full"}'
# Step 3: Check job status (poll until completed)
curl "https://pronostico.locura.tech/api/v1/analysis/job_q1r2s3t4" \
-H "Authorization: Bearer lk_live_abc123def456"
# Step 4: Get results
curl "https://pronostico.locura.tech/api/v1/analysis/job_q1r2s3t4/results" \
-H "Authorization: Bearer lk_live_abc123def456"Python
import requests
import time
API_KEY = "lk_live_abc123def456ghi789jkl012mno345"
BASE_URL = "https://pronostico.locura.tech/api/v1"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
# Step 1: Push sales data
upload = requests.post(
f"{BASE_URL}/data/sales",
headers=headers,
json={
"rows": [
{"sku": "SKU-001", "date": "2026-01-15", "quantity": 120, "revenue": 4560.00},
{"sku": "SKU-001", "date": "2026-02-15", "quantity": 135, "revenue": 5130.00},
{"sku": "SKU-002", "date": "2026-01-15", "quantity": 45, "revenue": 1350.00}
]
}
).json()
print(f"Upload: {upload['data']['upload_id']}")
# Step 2: Start analysis
analysis = requests.post(
f"{BASE_URL}/analysis/run",
headers=headers,
json={"type": "full"}
).json()
job_id = analysis["data"]["job_id"]
print(f"Analysis started: {job_id}")
# Step 3: Poll for completion
while True:
status = requests.get(
f"{BASE_URL}/analysis/{job_id}",
headers=headers
).json()
if status["data"]["status"] == "completed":
print("Analysis completed!")
break
elif status["data"]["status"] == "failed":
print("Analysis failed!")
break
print(f"Progress: {status['data']['progress']}%")
time.sleep(5)
# Step 4: Get results
results = requests.get(
f"{BASE_URL}/analysis/{job_id}/results",
headers=headers
).json()
summary = results["data"]["summary"]
print(f"Analyzed {summary['total_skus']} SKUs")
print(f"Recommendations: {summary['recommendations_count']}")JavaScript
const API_KEY = 'lk_live_abc123def456ghi789jkl012mno345';
const BASE_URL = 'https://pronostico.locura.tech/api/v1';
const headers = {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
};
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function runAnalysis() {
// Step 1: Push sales data
const upload = await fetch(`${BASE_URL}/data/sales`, {
method: 'POST',
headers,
body: JSON.stringify({
rows: [
{ sku: 'SKU-001', date: '2026-01-15', quantity: 120, revenue: 4560.00 },
{ sku: 'SKU-001', date: '2026-02-15', quantity: 135, revenue: 5130.00 },
{ sku: 'SKU-002', date: '2026-01-15', quantity: 45, revenue: 1350.00 }
]
})
}).then(r => r.json());
console.log(`Upload: ${upload.data.upload_id}`);
// Step 2: Start analysis
const analysis = await fetch(`${BASE_URL}/analysis/run`, {
method: 'POST',
headers,
body: JSON.stringify({ type: 'full' })
}).then(r => r.json());
const jobId = analysis.data.job_id;
console.log(`Analysis started: ${jobId}`);
// Step 3: Poll for completion
let status;
do {
await sleep(5000);
status = await fetch(`${BASE_URL}/analysis/${jobId}`, { headers })
.then(r => r.json());
console.log(`Progress: ${status.data.progress}%`);
} while (status.data.status !== 'completed' && status.data.status !== 'failed');
// Step 4: Get results
const results = await fetch(
`${BASE_URL}/analysis/${jobId}/results`,
{ headers }
).then(r => r.json());
const summary = results.data.summary;
console.log(`Analyzed ${summary.total_skus} SKUs`);
console.log(`Recommendations: ${summary.recommendations_count}`);
}
runAnalysis();4. Check Document Generation Status
Python
import requests
import time
API_KEY = "lk_live_abc123def456ghi789jkl012mno345"
BASE_URL = "https://docmaker.locura.tech/api/v1"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
# List active generation jobs
jobs = requests.get(
f"{BASE_URL}/jobs",
headers=headers,
params={"status": "processing"}
).json()
for job in jobs["data"]:
print(f"Job {job['id']}: {job['document_type']} - {job['progress']}%")
# Wait for a specific job to complete
job_id = "gjob_e5f6g7h8"
while True:
job = requests.get(
f"{BASE_URL}/jobs/{job_id}",
headers=headers
).json()
status = job["data"]["status"]
progress = job["data"]["progress"]
step = job["data"].get("current_step", "")
print(f"[{progress}%] {step}")
if status == "completed":
doc_id = job["data"]["document_id"]
print(f"Document ready: {doc_id}")
# Download the document
response = requests.get(
f"{BASE_URL}/documents/{doc_id}/download",
headers=headers
)
with open("document.pdf", "wb") as f:
f.write(response.content)
print("Downloaded: document.pdf")
break
elif status == "failed":
print("Generation failed!")
break
time.sleep(3)Changelog
Tracker shipment monitoring API
- Tracker API: 11 operations for UPS/DHL shipment monitoring, exception handling, imports and operational usage.
POST /api/v1/ingest/orders: idempotent store, ERP and WMS shipment ingestion with allowlisted callback URLs.- Signed source callbacks use HMAC-SHA256, stable idempotency keys and retryable outbox delivery.
- OpenAPI 3.1 JSON and Swagger UI are published by Tracker.
Consenso joins the API directory; full ecosystem coverage
- Consenso API — 13 operations for S&OP planning: cycles with Pronostico baseline ingest, demand consensus, planning economics & budget targets, product families and per-tenant Pronostico connection. Session-authenticated (Hub SSO);
GET /api/v1/healthis public. - Modeler listed in the directory — 3D warehouse design studio; public REST API in development.
- Pronostico: documented
POST /api/v1/data/models(model grouping, carton size, model-level MOQ) andPOST /api/v1/data/sku-moq(per-SKU minimum order quantities).
Efectiver joins the API directory
- Efectiver API — 8 endpoints for multi-tenant workforce performance, bonus and competency analytics (foundation for EU Pay Transparency, Directive 2023/970).
POST /api/v1/onboarding— provision a tenant (admin-key authenticated).POST /api/v1/auth/login+/logout— session cookie auth.POST /api/v1/ingest/{source}— per-source API-key push connector (up to 50 000 events/request).GET /api/v1/performance— per-worker totals, heatmap, daily KPIs, trend, optional MoM.GET /api/v1/competency/coverage+POST /competency/suggest+/suggest/{id}/approve— competency matrix, bus-factor risk and human-in-the-loop AI suggestions.
Validator joins the API directory
- Validator API — universal evidence-grounded document-compliance engine (cited answers vs standards, laws & procedures); currently trained on the power-tools domain, applicable to legal, pharma and any document-heavy field.
GET /api/v1/health— public health check with db + embeddings status.- Compliance chat, document library, audit and source-diff are session-authenticated in the web UI; public REST endpoints are on the roadmap.
Pronostico: read-side endpoints
GET /api/v1/data/sales/list— read deduped sales transactions with SKU/date/customer filters and pagination.GET /api/v1/data/stock/snapshots— stock snapshot history;latest_only=1for current inventory only.GET /api/v1/customers+/{id}— customer rankings with revenue/order stats and per-SKU breakdown.GET /api/v1/sku/{sku}— single-call snapshot: classification + forecast + recommendation + history + customers.- Premise: every dataset Pronostico stores is now retrievable via the API for ERP reconciliation.
DocMaker Control Plane
- DocMaker API now exposes 13 read operations.
- Configurable document type registry with immutable definition versions, dynamic forms, validation rules, output formats, and template pins.
- Versioned template catalog and governance release snapshots remain available through the same tenant-scoped document read permission.
- Public responses exclude prompts and internal storage paths.
Initial Release
- REST API v1 with unified authentication across all LOCURA apps
- Hub API -- 16 endpoints: clients, files (R2), API keys, webhooks, usage, GDPR, sandbox
- Pronostico API -- 15 endpoints: data push (sales, stock, POs, prices), analysis, classifications, forecasts, recommendations, suppliers (extended to 20 in v1.1.0)
- Avisator API -- 16 endpoints: locations, docks, bookings, suppliers, vehicles, slots, dock map
- DocMaker API -- 6 endpoints: documents, download, generation jobs
- Validator API -- 1 public endpoint: health (compliance chat, library, audit, standards-diff endpoints on roadmap)
- Webhook system with HMAC-SHA256 verification and exponential retry backoff
- Rate limiting with 3 tiers (free: 60/min, pro: 300/min, enterprise: 1000/min)
- RFC 7807 Problem Details error format
- Sandbox environment with test keys (lk_test_*)
- Swagger UI available for all 4 applications