fragtr

Fragtr API

Med API'et kan jeres eget system (lager, ERP, webshop) hente priser, booke forsendelser, hente labels og følge tracking direkte i fragtr. Priserne er præcis de samme som i portalen.

Kom i gang

  1. Log ind i fragtr og gå til Backend → API-nøgler → Opret nøgle. Vælg Kun læse eller Læse og booke.
  2. Kopiér nøglen (fk_…). Den vises kun én gang – opbevar den som en adgangskode.
  3. Send nøglen i hver forespørgsel: Authorization: Bearer fk_…

Basis-adresse: https://fragtr.dk/api/v1 · Alle beløb er DKK ekskl. moms · JSON ind og ud · Datoer som ÅÅÅÅ-MM-DD.

curl https://fragtr.dk/api/v1/me \
  -H "Authorization: Bearer fk_DIN_NØGLE"

En kundes nøgle arbejder altid på kundens egen konto. En organisations nøgle kan arbejde på organisationens kunder (angiv account_no) eller som egen forsendelse ("account_no": "own").

Endpoints

MetodeStiHvadAdgang
GET/meHvem nøglen tilhørerLæse
GET/accountsKonti nøglen kan arbejde på (?q= søger)Læse
POST/quotesHent priser – returnerer quote_id og tilbud (gælder 30 min.)Læse
POST/bookingsBook et tilbudBooke
GET/bookingsListe – ?from=&to=&status=&q=&account_no=&limit=Læse
GET/bookings/{nr}Én booking (fx CL-2026-00012). ?refresh=1 henter seneste statusLæse
GET/bookings/{nr}/labelLabelen som PDFLæse
POST/bookings/{nr}/cancelAnnullér (kun før afhentning)Booke
GET/statsNøgletal for en periode – ?from=&to=Læse

Status på en booking: booked, handling (behandles manuelt), failed, error (kan prøves igen), cancelled. Kurérens egen status ligger i carrier_status.

Pris og booking

1. Hent priser

POST /api/v1/quotes
{
  "direction": "export",                  // export (fra DK) · import (til DK) · cross (mellem to andre lande)
  "origin":      {"country": "DK", "zip": "2600", "city": "Glostrup", "street": "Industrivej 4"},
  "destination": {"country": "NO", "zip": "0162", "city": "Oslo", "street": "Karl Johans gate 12"},
  "packages": [{"qty": 2, "kg": 4.5, "l": 40, "w": 30, "h": 30}],
  "pickup_date": "2026-10-27",            // valgfri – standard er næste hverdag
  "incoterm": "DAP"                       // valgfri
}
{
  "quote_id": "4f1c…", "valid_minutes": 30,
  "offers": [
    {"offer_id": "ntg:42", "carrier": "UPS", "product_label": "UPS · Standard", "sell_dkk": 215.32,
     "transit_hint": "Levering senest fre. kl. 23:30"}
  ]
}

2. Book

POST /api/v1/bookings
{
  "quote_id": "4f1c…",
  "offer_id": "ntg:42",
  "sender":   {"name": "Nordlys Lager", "contact": "Pia", "street": "Industrivej 4", "phone": "+45 12 34 56 78",
               "email": "lager@nordlys.dk"},
  "receiver": {"name": "Bergen Interiør AS", "contact": "Ola", "street": "Karl Johans gate 12",
               "phone": "+47 22 33 44 55", "email": "ola@bergen.no"},
  "goods_description": "Bordlamper i messing",    // påkrævet – hvad er der i pakken
  "reference": "ORD-1001",                        // valgfri
  "commodity_value": 4800                         // kun toldpligtige forsendelser (fx Norge, UK, USA)
}

Postnr., by og land tages fra prisen. Telefon på afsender og modtager er påkrævet. Ved import og cross trade skal afsenderens e-mail udfyldes (labelen sendes dertil). Svaret indeholder bookingen med no, tracking_number og has_label.

3. Label

curl -o label.pdf https://fragtr.dk/api/v1/bookings/CL-2026-00012/label -H "Authorization: Bearer fk_…"

Webhooks

Under Backend → Webhook angiver I en https-adresse. Fragtr sender så en POST med JSON, når noget sker:

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

{"event": "booking.updated", "sent_at": "2026-10-23T09:12:00+00:00",
 "data": {"booking": {"no": "CL-2026-00012", "status": "booked", "tracking_number": "1Z…",
                      "carrier_status": {"code": "IN_TRANSIT", "label": "Undervejs", …}, …}}}

Tjek signaturen

Signaturen er HMAC-SHA256 af "{timestamp}.{body}" med jeres signeringsnøgle (whsec_…, vises én gang). Afvis beskeder, hvor signaturen ikke passer, eller tidsstemplet er mere end 5 minutter gammelt.

# Python
import hmac, hashlib, time
def ok(secret, ts, body, signature):
    expected = "sha256=" + hmac.new(secret.encode(), f"{ts}.{body}".encode(), hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature) and abs(time.time() - int(ts)) < 300
// Node.js
const crypto = require("crypto");
function ok(secret, ts, body, signature) {
  const expected = "sha256=" + crypto.createHmac("sha256", secret).update(`${ts}.${body}`).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature)) && Math.abs(Date.now()/1000 - ts) < 300;
}

Svar med 2xx inden for 6 sekunder. Brug Send test i Backend for at prøve forbindelsen.

Fejl og grænser

Fejl returneres som {"error": "Forklaring på dansk"} med HTTP-status: 400 ugyldige data, 401 manglende/ugyldig nøgle, 403 ikke adgang (fx læse-nøgle der prøver at booke), 404 findes ikke, 429 for mange kald, 502 kurérsystemet svarede ikke – prøv igen.

Højst 120 kald pr. minut pr. nøgle. Slet en nøgle under Backend, hvis den er kommet i forkerte hænder – den holder op med at virke med det samme.

Claude (MCP)

Clovr og organisationer kan forbinde Claude til fragtr og spørge om omsætning, avance, bookinger og fakturaer – eller lade Claude hente priser og booke. Claude ser kun det, brugeren selv kan se, og spørger før den ændrer noget.

  1. I Claude: Indstillinger → Connectors → Tilføj brugerdefineret connector.
  2. URL: https://fragtr.dk/mcp → Forbind → log ind med dit fragtr-login → Tillad adgang.

Claude Code eller andre MCP-klienter kan også bruge en API-nøgle:

claude mcp add --transport http fragtr https://fragtr.dk/mcp \
  --header "Authorization: Bearer fk_DIN_NØGLE"