API Documentation

REST API for external integration. Access articles, stock, orders, receptions and more via Bearer token.

Login
Overview

The API allows external systems (ERP, mobile apps) to read and write operational data in 3PL Client (articles, orders, receptions, returns, webhooks, and reference data). Authentication uses Bearer tokens (Laravel Sanctum). All data endpoints require authentication.

Each route also requires the API module and the matching content module (e.g. inbound for receptions) to be enabled for the company in X-Company-Id.

Base URL: https://flowscmc.org/api

Machine-readable OpenAPI 3.0 specification (paths aligned with this API): https://flowscmc.org/openapi.json

Authentication

Obtain a Bearer token by sending email and password:

POST https://flowscmc.org/api/auth/token
Content-Type: application/json

{
  "email": "your@email.com",
  "password": "your-password"
}

// Response:
{
  "token": "1|abc123...",
  "user": { "id": 1, "name": "...", "email": "..." }
}

Use the token in all subsequent requests:

Authorization: Bearer 1|abc123...

To revoke the current token (logout):

POST https://flowscmc.org/api/auth/revoke
Authorization: Bearer 1|abc123...
Company context

To filter data by company, send the optional header:

X-Company-Id: 123

The user must have access to the specified company. Without this header, super-admins see all companies; regular users see their primary company.

UM 3PL quantities on order lines

When defining an article, the first unit of measure in the system (field um3pl, UM 3PL in the UI) must be the one used for physical warehouse handling. UM2 and UM3 are for higher packaging levels when needed.

Purchase orders, sales orders, receptions, and returns use line fields um3pl and quantity_um3pl. You may send decimals with a comma (e.g. 1,5); the API normalizes to a dot before validation.

If the article requires whole-number UM 3PL quantities, or the 3PL stock-unit catalog marks that UM code as integer-only, quantity_um3pl must be a whole number. Otherwise validation fails with the standard error payload.

eTSM inbound (shared Bearer, not Sanctum)

Configure ETSM_INBOUND_BEARER_TOKEN in the environment. Use Authorization: Bearer <that token>. For creating receptions, call POST /api/integrations/etsm/receptions with the same JSON body as POST /api/receptions and header X-Company-Id set to the client company id. GET /api/integrations/etsm/ping verifies the token.

GET https://flowscmc.org/api/integrations/etsm/ping
Authorization: Bearer <ETSM_INBOUND_BEARER_TOKEN>

POST https://flowscmc.org/api/integrations/etsm/receptions
Authorization: Bearer <ETSM_INBOUND_BEARER_TOKEN>
X-Company-Id: 123
Content-Type: application/json

{ ... same JSON as POST /api/receptions ... }
Pagination

List endpoints support pagination via query parameters:

?page=1&per_page=25

Default per_page: 25. Maximum per_page: 100 (200 for stock). Response includes meta and links.

Available endpoints
Method Endpoint Description
GET /api/health Health check for monitoring (no auth required)
GET /api/integrations/etsm/ping eTSM connectivity check (shared Bearer; 503 if token not configured)
POST /api/integrations/etsm/receptions Create reception from eTSM (X-Company-Id required; same rules as /api/receptions)
GET /api/companies Accessible 3PL client companies for the authenticated user (playground company picker)
GET /api/articles List articles (paginated)
GET /api/articles/sync Incremental article sync (updated_since, cursor)
POST /api/articles Create article
GET /api/articles/{id} Article details
PUT /api/articles/{id} Update article
GET /api/stock Stock levels (paginated, max 200/page)
GET /api/sales-orders Sales orders (paginated)
POST /api/sales-orders Create sales order
GET /api/sales-orders/{id} Sales order details
PUT /api/sales-orders/{id} Update sales order
GET /api/purchase-orders Purchase orders (paginated)
POST /api/purchase-orders Create purchase order
GET /api/purchase-orders/{id} Purchase order details
PUT /api/purchase-orders/{id} Update purchase order
GET /api/receptions Receptions (paginated)
POST /api/receptions Create reception
GET /api/receptions/{id} Reception details
PUT /api/receptions/{id} Update reception
GET /api/returns Returns (limit 100)
POST /api/returns Create return
GET /api/returns/{id} Return details
GET /api/webhooks Webhooks list
POST /api/webhooks Create webhook
GET /api/webhooks/{id} Webhook details
PUT /api/webhooks/{id} Update webhook
DELETE /api/webhooks/{id} Delete webhook
GET /api/clients List 3PL client companies (paginated)
GET /api/clients/{id} 3PL client company details
GET /api/partners Partners list (paginated)
GET /api/partners/{id} Partner details
GET /api/warehouses Warehouses list (paginated)
GET /api/warehouses/{id} Warehouse details
GET /graphql GraphQL endpoint – Query articles and other data via GraphQL. Requires Bearer token and X-Company-Id header.
GraphQL endpoint

Query articles and other data via GraphQL. Requires Bearer token and X-Company-Id header.

Base URL: https://flowscmc.org/graphql

Example query – list articles:

POST https://flowscmc.org/graphql
Authorization: Bearer YOUR_TOKEN
X-Company-Id: 1
Content-Type: application/json

{
  "query": "{ articles(limit: 10) { id article_code description } }"
}

Use the same Bearer token and X-Company-Id header as for REST endpoints.

Health check (JSON)

GET /api/health returns the same JSON as GET /health and GET /up (no auth). The body includes aggregate checks, heartbeats (per scheduler name, last ping, ok), integrations and modules. If the heartbeats table is empty, items contains a placeholder row for cron and no_records is true until the scheduler runs heartbeat:ping.

{
  "status": "healthy",
  "app": { "name": "3PL", "env": "production" },
  "urls": {
    "app": "https://example.com",
    "api": "https://example.com/api"
  },
  "checks": {
    "database": true,
    "cache": true,
    "queue": true,
    "redis": true,
    "storage": true,
    "storage_public": true,
    "heartbeat": true
  },
  "heartbeats": {
    "stale_after_minutes": 15,
    "no_records": false,
    "items": [
      { "name": "cron", "last_ping_at": "2026-04-09T12:00:00.123456Z", "last_ping_at_ms": 1775736000123, "ok": true }
    ]
  },
  "integrations": { "anaf": true },
  "modules": [ { "slug": "api", "name": "API" } ],
  "timestamp": "2026-04-09T12:00:00+00:00"
}

urls.app and urls.api come from APP_URL (base app and /api). Prometheus: append ?format=prometheus. Web UI with live heartbeats: Platform → Health (super-admin).

Example request
curl -X GET "https://flowscmc.org/api/articles" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Company-Id: 1" \
  -H "Accept: application/json"
Rate limiting
  • POST /api/auth/token: 10 requests per minute
  • Data endpoints: 60 requests per minute
API Playground

Test API endpoints directly from this page. First obtain a token, then select an endpoint and send the request.

1
Obtain token
2
Test endpoint
Ready to integrate?

Log in to create Bearer tokens and access the API.

Login

We use essential cookies for the application to work. Optional cookies help us improve the experience. Learn more