Skip to main content
Version: 1.0.8

REST Endpoints

A pipeline can publish an HTTP endpoint. An ERP posts an order, an MES asks for line status, a label printer requests the next job — each arrives as a message that runs your graph and returns whatever you build.

Published routes are served by the RestGateway on port 8090, under the project's slug:

http(s)://<host>:8090/gateway/<project-slug><URL pattern>

A route published as /api/v1/orders in the project plant-a is called at /gateway/plant-a/api/v1/orders. The node's editor shows the full path under the URL pattern.

Building one​

REST API (ingress) → Python (validate) → MongoDB (insert) → HTTP Response
  1. REST API node in ingress mode defines the method and URL pattern.
  2. Middle nodes do the work.
  3. HTTP Response sends the reply. Every ingress path must reach one, or the caller waits for the timeout.

Route configuration​

SettingDefaultPurpose
MethodGETGET, POST, PUT, DELETE, PATCH, or * for any.
URL pattern/api/v1/exampleThe route's path. No :id placeholders — see Matching.
Timeout30 sHow long the caller waits before the gateway gives up.
AuthPublic (No Auth) on a new nodeAPI Key (X-API-Key) or Public (No Auth).
Required scopes(none)Capability scopes the caller's key must hold, e.g. tag:write,db:read.
Allowed IPs(any)Comma-separated CIDR allow-list.
Rate limit0 (off)Requests per second.
Burst limit0Burst size above the sustained rate.
Max payload size1 MBRequest body cap.
CORS enabledfalseAllow browser cross-origin calls.
Allowed origins*Origins permitted when CORS is on.

Matching​

A request is matched, in order, to the route with the same method and path; then to a route whose method is *; then to the route whose path the request's path begins with. So /api/v1/orders/SO-1042 reaches a route published as /api/v1/orders. There are no path parameters: pass identifiers in the query string, or read the full request path from the message's origin (below). A trailing slash is ignored.

Choose the authentication deliberately​

A new REST API node starts Public (No Auth), and the editor says so in an amber warning: anyone who can reach it can invoke its pipeline. Set API Key (X-API-Key) for anything outside a test bench. Behind that choice the gateway fails closed: a route whose auth setting is anything other than public or a valid API key is refused.

API keys​

Keys are project-scoped credentials. Create them where they are used: in a REST API ingress node, set the authentication to API Key (X-API-Key) and use Project API Keys → Create Key. Listing, creating and revoking keys requires Access Settings.

  • The key value is shown once, at creation. Only a hash is stored.
  • Revocation is immediate.
  • Give each consumer its own key, so one can be revoked without disrupting the others.

→ API keys

Scopes​

A key carries capability scopes; a route can require some. A key without a required scope is rejected even though it is otherwise valid.

Key "mes-integration" scopes: db:read, tag:read
Route POST /api/v1/setpoint requires: tag:write → rejected
Route GET /api/v1/status requires: tag:read → allowed

Scopes let one key serve several routes at a bounded level of privilege.

Defence in depth​

Layer the controls; each is cheap and independent.

ControlStops
API keyUnauthenticated callers
ScopesAn authenticated caller doing more than it should
IP allow-listCalls from outside the expected network
Rate limit + burstRunaway clients and brute-force attempts
Max payload sizeMemory-exhaustion attempts
CORS offBrowser-based cross-origin abuse

An integration endpoint for a known MES should have: an API key, the narrowest scopes, the MES's CIDR, a rate limit slightly above its real traffic, and CORS off.

Calling an endpoint​

curl -X POST https://qubiq.example.com:8090/gateway/plant-a/api/v1/orders \
-H "X-API-Key: <key>" \
-H "Content-Type: application/json" \
-d '{"orderId":"SO-1042","line":"L1","qty":500}'

Reading request data​

The request arrives as the message payload:

FieldHolds
paramsThe query string, one value per name: ?line=L1 → {"line": "L1"}
bodyA JSON body, parsed. Any other body arrives as text
form · filesA form post's fields, and its uploaded files (name, size, type and the content as base64)

The request line and headers are in the message's origin: message["origin"]["ctx"] holds method, path (which includes the project slug), query, headers and client_ip, the caller address the gateway trusts.

def transform(payload, message):
order = payload.get("body") or {}
if not order.get("orderId"):
return {"http_status": 400, "error": "orderId is required"}

system.db.runNamedQuery("insert_order", {
"id": order["orderId"],
"line": order.get("line"),
"qty": order.get("qty", 0),
})
return {"http_status": 201, "accepted": order["orderId"]}

The HTTP Response node after it takes the status from http_status and sends the rest of the payload as the body; an error field answers {"error": "…"} instead.

Credentials never reach pipeline code: Authorization, Cookie, X-Api-Key, X-Auth-Token and Proxy-Authorization are removed from the headers, and so are X-Forwarded-For and X-Real-Ip, which a caller can forge.

Outbound calls (egress)​

The same node in egress mode calls out: post an alarm to a webhook, fetch a work order, push a report to an external API.

SettingPurpose
URL, methodThe target
Static headersAdded to every request (e.g. an authorization header)
TimeoutGive up after this long

Egress calls are not buffered by store-and-forward: a call that fails, fails, and nothing replays it later. When the event must not be lost, write it somewhere durable first.

Operational notes​

  • Port 8090 must be reachable by the caller; it is separate from the UI port.
  • The pipeline must be running. A stopped pipeline's routes return an error.
  • Version your URLs (/api/v1/...). Changing a pipeline's response shape breaks callers exactly as changing any API does.
  • Return meaningful status codes from the HTTP Response node. A 200 carrying an error message is hostile to whoever integrates with you at 03:00.

Troubleshooting​

SymptomCheck
404The /gateway/<project-slug> prefix is missing or wrong, the pipeline is stopped, or no route matches the method and path.
401Missing, unknown or revoked API key.
403Missing required scope, or source IP outside the allow-list.
413Body exceeds max payload size.
429Rate limit hit — raise it or fix the client.
504 after the route timeoutNo HTTP Response node was reached on that path.
503 No pipeline handler availableThe route is known but no running pipeline is listening behind it.
CORS error in a browserCORS disabled, or the origin is not in the allowed list.

Next​

→ Designer