API Reference
Vectis provides a REST API for orders, products, inventory, and webhooks, documented in OpenAPI 3.1, with HMAC-signed webhooks.
Base URL
API requests use your tenant subdomain:
https://{tenant}.vectisoms.app
Where {tenant} is your organization’s subdomain (e.g., acme.vectisoms.app). Endpoint paths below already include the /api prefix (except /health), so a full URL looks like https://acme.vectisoms.app/api/orders.
Authentication
All API requests require a Bearer token in the Authorization header, obtained via OAuth 2.0 client credentials flow.
Obtaining a Token
Request an access token from the OAuth endpoint:
curl -X POST https://api.vectisoms.app/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET"
Response:
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "orders:read orders:write inventory:read inventory:write products:read products:write"
}
Making Requests
Include the token in the Authorization header:
curl https://acme.vectisoms.app/api/orders \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Organization owners create API Clients in the Vectis account portal (the Control Plane link in the app sidebar), under Organization Settings → Developer → API Clients. (The same tab also lists API Keys; for the Vectis API, use an API Client.) The secret is shown once. Contact support@stoalogistics.com if you need assistance.
API client tokens currently have read access to orders, products, and inventory, and can manage webhook subscriptions. To create or change orders, products, or inventory through the API, contact support@stoalogistics.com.
Common Endpoints
Orders
| Method | Endpoint | Description |
|---|---|---|
GET | /api/orders | List orders with filtering and pagination |
POST | /api/orders | Create a new order |
POST | /api/orders/bulk-import | Bulk import up to 500 orders (JSON body with format and data: an array of orders or CSV text) |
GET | /api/orders/{id} | Get order details |
PATCH | /api/orders/{id} | Confirm an order or mark it delivered (status: confirmed or delivered) |
POST | /api/orders/{id}/cancel | Cancel an order |
Products
| Method | Endpoint | Description |
|---|---|---|
GET | /api/products | List products |
POST | /api/products | Create a product |
GET | /api/products/{id} | Get product details |
GET | /api/products/sku/{sku} | Get product by SKU |
PATCH | /api/products/{id} | Update product |
DELETE | /api/products/{id} | Delete a discontinued product (soft delete) |
Inventory
| Method | Endpoint | Description |
|---|---|---|
GET | /api/inventory | List inventory levels |
POST | /api/inventory | Create inventory record |
GET | /api/inventory/{id} | Get inventory item |
PATCH | /api/inventory/{id}/adjust | Adjust inventory quantity |
Webhooks
| Method | Endpoint | Description |
|---|---|---|
GET | /api/webhooks | List webhook subscriptions |
POST | /api/webhooks | Create webhook subscription |
DELETE | /api/webhooks/{id} | Delete webhook subscription |
System
| Method | Endpoint | Description |
|---|---|---|
GET | /health | System health check |
Request Format
Most requests use JSON. Bulk order import takes a JSON body {"format": "json", "data": [orders]} or {"format": "csv", "data": "<csv text>"} (one order per row); see POST /api/orders/bulk-import.
Order creation request body:
POST /api/orders
Content-Type: application/json
Authorization: Bearer <access_token>
{
"externalId": "SHOP-12345",
"customerId": "cust_john123",
"customerEmail": "john@example.com",
"items": [
{ "sku": "WIDGET-BLU", "quantity": 2 },
{ "sku": "GADGET-RED", "quantity": 1 }
],
"shippingAddresses": [{
"name": "John Doe",
"line1": "123 Main St",
"city": "Phoenix",
"region": "AZ",
"postalCode": "85001",
"country": "US"
}],
"billingAddress": {
"name": "John Doe",
"line1": "123 Main St",
"city": "Phoenix",
"region": "AZ",
"postalCode": "85001",
"country": "US"
}
}
Line prices come from your product catalog.
Addresses
Shipping and billing address objects accept line1 as today, and also street1 as an alias for the same field. Use whichever your upstream system already emits.
Order line items in responses
When present on an order, line items may include cost fields for operations and integrations: unitCost, costCurrency, and lineCost. Treat them as optional; availability can depend on your catalog and tenant configuration.
Response Format
Successful responses return JSON with the resource:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "pending",
"total": 109.97,
"itemCount": 3,
"createdAt": "2026-01-15T10:30:00Z"
}
Errors return a non-2xx status and a JSON body with an error field. Depending on the endpoint, error is a message string, an object with code and message, or, for request validation failures (HTTP 400), an object with an issues list. Branch on the HTTP status code.
Pagination
The order and product lists support pagination (limit default 20, max 100; offset default 0):
GET /api/orders?limit=50&offset=0
Paginated list responses include limit, offset, and total inside the pagination object so you know how many records match the query, not just the current page.
Response includes pagination metadata:
{
"orders": [...],
"pagination": {
"limit": 50,
"offset": 0,
"total": 1234
}
}
Filtering
Filter by query parameters:
GET /api/orders?status=pending&q=SHOP-12345&fromDate=2026-01-01
Webhooks
Create webhooks through the API (the dashboard form doesn’t send the required signing secret yet), then manage, test, and view deliveries in Settings → Webhooks. All webhooks are signed with HMAC-SHA256.
Verifying Signatures
Each delivery includes X-Vectis-Signature: t=<timestamp>,v1=<signature>. Compute HMAC-SHA256 of <timestamp>.<raw request body> with your webhook secret, compare the hex digest with v1 in constant time, and reject timestamps older than five minutes. Deliveries also carry X-Vectis-Event and X-Vectis-Delivery-Id. See the Webhooks Guide for code.
Event Types
Subscribe with the event names below, or * for all events. Each delivery names its event in the event field and the X-Vectis-Event header: OrderCreated, OrderConfirmed, OrderCancelled, OrderShipped, OrderDelivered, PackageCreated, PackageShipped, PackageDelivered, InventoryAdjusted.
Rate Limits
Rate limits are not published for the tenant API. Some features, such as AI demand forecasting, have their own limits. A 429 whose body has "error": "LIMIT_EXCEEDED" means a plan limit (for example warehouses, carrier accounts or sales channels); retrying won’t clear it. Any other 429 is temporary: wait and retry with backoff.
Idempotency
To retry POST /api/orders safely, send an Idempotency-Key header. A repeat request with the same key within 24 hours returns the original order instead of creating a new one. externalId is not checked for duplicates. No other endpoint on this page supports idempotency keys.
OpenAPI Specification
The public OpenAPI 3.1 spec is at https://stoalogistics.com/openapi.json. Browse it interactively in the API Reference.
SDKs
There are no official SDKs. Use any HTTP client with the REST API.
Support
- API questions: support@stoalogistics.com
- Bug reports: support@stoalogistics.com