fragtr›API›Custom order systemDansk · English

Custom order system

For your own system – e.g. an ERP, a warehouse system or a webshop we don't have a ready-made integration for. The system sends orders to fragtr, can show your shipping methods in its own checkout, and gets the tracking number back once the order is booked.

Getting startedSend ordersShipping in checkoutTracking backErrors

Getting started

  1. Go to Backend → Order systems → + Connect order system → Custom. Give it a name and optionally a webhook URL.
  2. Copy the key (fco_…). It is shown only once – create a new one under the webshop if you lose it.
  3. Send the key with every request: Authorization: Bearer fco_…
  4. Create shipping methods on the connection (click it under Order systems) if your checkout should show shipping options.

All URLs start with https://fragtr.dk/api/v1/shop. Data is sent and received as JSON.

RequestWhat it does
POST /ordersCreate an order – or update it if it has not been booked yet (same order_id).
GET /orders/{order_id}Status, booking and tracking number.
DELETE /orders/{order_id}The order was cancelled on your side – moved to Ignored (if it has not been booked).
GET /methodsYour visible shipping methods.
POST /ratesShipping options and prices for checkout based on country, weight and cart.

Send orders

POST https://fragtr.dk/api/v1/shop/orders
Authorization: Bearer fco_…
Content-Type: application/json

{
  "order_id": "SO-1001",              // your own id (required, unique)
  "number": "1001",                   // shown in fragtr and used as reference
  "ordered_at": "2026-10-24T10:30:00Z",
  "shipping_method": "fragtr-12",     // code from /rates or /methods (optional)
  "currency": "DKK",
  "total": 800.00,                    // value of the goods – used for customs outside the EU
  "receiver": {
    "name": "Bergen Interiør AS", "contact": "Ola Nordmann",
    "street": "Karl Johans gate 12", "street2": "", "zip": "0162", "city": "Oslo",
    "country": "NO", "email": "ola@bergen.no", "phone": "+47 22 00 00 00"
  },
  "items": [
    {"name": "Bordlampe messing", "qty": 2, "price": 400.00, "weight_kg": 1.1,
     "sku": "L-1", "hs_code": "940520", "origin_country": "DK"}
  ]
}

Response 201 (new) or 200 (updated):

{"order": {"order_id": "SO-1001", "number": "1001", "status": "new", "shipping_method": "fragtr-12", "booking": null}}

The order appears under My bookings → Webshop orders. If it has a shipping_method, it can be booked with one click – otherwise you choose a rate in fragtr.

Shipping in checkout

Call /rates when the customer chooses shipping. The response contains your own shipping methods with the prices you have set up – only those that cover the country, weight and cart.

POST https://fragtr.dk/api/v1/shop/rates
Authorization: Bearer fco_…

{"country": "NO", "items": [{"qty": 2, "price": 400.00, "weight_kg": 1.1}]}
{"rates": [
  {"code": "fragtr-12", "name": "Levering til døren",
   "description": "1–3 hverdage · Told og moms betales af modtageren ved levering",
   "price": 149.0, "currency": "DKK"}
]}

Store the selected code and send it as shipping_method when the order is sent to fragtr.

Tracking back

If you have set a webhook, fragtr sends a POST as soon as the order is booked and the tracking number is available:

POST https://jeres-system.dk/fragtr/webhook
X-Fragtr-Event: order.shipped
X-Fragtr-Timestamp: 1792700000
X-Fragtr-Signature: sha256=5d1c…

{"event": "order.shipped", "sent_at": "2026-10-24T11:02:00+00:00",
 "data": {"order_id": "SO-1001", "tracking_number": "1Z999AA10123456784",
          "tracking_url": "https://www.ups.com/track?tracknum=1Z999AA10123456784", "carrier": "UPS"}}

The signature is HMAC-SHA256 of "{timestamp}.{body}" using the order system's key (fco_…). Respond with 2xx within 8 seconds – otherwise we retry later.

# Python
import hmac, hashlib, time
def ok(key, ts, body, signature):
    expected = "sha256=" + hmac.new(key.encode(), f"{ts}.{body}".encode(), hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature) and abs(time.time() - int(ts)) < 300

Without a webhook, your system can fetch the status itself with GET /orders/{order_id}.

Errors and limits

Errors are returned as {"error": "Explanation"}: 400 invalid data, 401 missing or invalid key, 403 the account is blocked, 404 not found, 409 the order is already booked, 423 the order system is paused, 429 too many requests (at most 120 per minute).

Send the header Accept-Language: en to get error messages in English (default is Danish).