Skip to main content

Send orders through the API channel

Send orders to a Hyperfox environment through its API channel when your system, such as a webshop or an ordering portal, should place orders with a supplier who works with Hyperfox: you post each order as JSON to the channel's Webhook URL, and the order appears in the supplier's Hyperfox for validation.

Before you begin​

Ask the supplier's Hyperfox admin for:

  • the Webhook URL of the API channel;
  • the field names of their orders and order lines, and which fields are required;
  • whether the channel checks a signature, and if so the token and the name of the signature header.

Send an order​

Post the order as JSON to the Webhook URL:

POST <Webhook URL>
Content-Type: application/json
Accept: application/json

{
"data": {
"customer_reference": "PO-2026-0412",
"notes": "Deliver before noon"
},
"attachments": []
}

Send Accept: application/json on every request, so that errors come back as JSON. The request needs no other authentication than the optional signature. A 200 response means the supplier's Hyperfox has received the order.

Request body​

KeyRequiredValue
datayesOne order as an object, or several orders as a list of objects.
attachmentsyesA list of files, which may be empty. See Attach files.
custom_order_idnoA UUID that you choose as the ID of the inquiry in Hyperfox, for example to find it back later.

Inside an order, each key is a field name of the supplier's orders. A key that is not a field name fills no field. A list field, such as the order lines, takes a list of objects with the field names of a line:

{
"data": {
"customer_reference": "PO-2026-0412",
"lines": [
{ "item_code": "A-100", "quantity": 4 },
{ "item_code": "B-220", "quantity": 1 }
]
},
"attachments": []
}

The field names in these examples are illustrations. Use the names the supplier gives you.

Send several orders in one request​

Send data as a list. Every object in the list becomes its own order, and the supplier validates them together:

{
"data": [
{ "customer_reference": "PO-2026-0412" },
{ "customer_reference": "PO-2026-0413" }
],
"attachments": []
}

An empty list is refused.

Attach files​

Each item in attachments holds either a url or a content, never both:

KeyValue
urlA web address of the file. Hyperfox downloads it. A file that cannot be downloaded is skipped without an error.
contentThe file, base64-encoded.
filenameOptional, with content. Without it, Hyperfox generates a file name with an extension that matches the type.
contentTypeOptional, with content, for example application/pdf. Without it, Hyperfox detects the type from the content.
"attachments": [
{ "url": "https://shop.example.com/orders/PO-2026-0412.pdf" },
{ "content": "JVBERi0xLjcK...", "filename": "PO-2026-0412.pdf", "contentType": "application/pdf" }
]

Sign the request​

When the channel has a token, sign every request:

  1. Compute the HMAC-SHA256 of the exact request body, byte for byte as you send it, with the token as the key.
  2. Write the result as lowercase hexadecimal.
  3. Send it in the signature header, by default X-HF-Signature, unless the supplier gave you another header name.

Sign the body after you serialise it, and send exactly those bytes: a change to the whitespace or the key order breaks the signature.

BODY='{"data":{"customer_reference":"PO-2026-0412"},"attachments":[]}'
SIGNATURE=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$TOKEN" | sed 's/^.* //')
curl -X POST "$WEBHOOK_URL" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "X-HF-Signature: $SIGNATURE" \
--data-raw "$BODY"
import hashlib, hmac, json, requests

body = json.dumps({"data": {"customer_reference": "PO-2026-0412"}, "attachments": []}).encode()
signature = hmac.new(token.encode(), body, hashlib.sha256).hexdigest()
requests.post(webhook_url, data=body, headers={
"Content-Type": "application/json",
"Accept": "application/json",
"X-HF-Signature": signature,
})

Responses​

StatusBodyMeaning
200{"status": "processed", "message": "Webhook processed successfully", "api_order_id": "<id>"}The order is received.
401{"error": "Missing signature", ...}The channel has a token and the signature header is missing.
401{"error": "Invalid signature", ...}The signature does not match the body.
403{"error": "API channel inactive", ...}The supplier has paused the channel. Hyperfox created no order; send the request again once the supplier has switched the channel back on.
400{"error": "Unsupported channel type", ...}The Webhook URL does not belong to an API channel.
404The channel does not exist, for example because the supplier deleted it.
422Validation errors per keyA key is missing or invalid, or an order breaks a rule of the supplier's orders.
422{"error": "Webhook processing failed", ...}The request could not be processed.

For a single order, a validation error names the field, such as customer_reference. For a list, it names the position and the field, such as data.1.customer_reference.

Things to know​

  • Every request creates new orders. Hyperfox does not recognise a request you send twice, so do not resend a request that received a 200.
  • Send each custom_order_id only once.
  • Whether an order waits for the supplier's validation or goes on to their ERP at once is the supplier's choice.