Raptors Freight & Packaging API v1
Book, price, track and pay for shipments from your own systems. Base URL: https://raptorsfreight.live/api/v1
Getting Started
- Log in and open Developer API; create a key, tick the scopes it needs, and copy it once.
- Send it as
Authorization: Bearer rfp_…on every call. JSON in, JSON out. - Start with a test key (
rfp_test_…): it reads your real data but never books or charges anything.
curl -H "Authorization: Bearer rfp_…" https://raptorsfreight.live/api/v1/usage
Authentication
Two credentials are accepted and behave the same: an API key from the Developer portal (long-lived, revocable, scoped) or a JWT from /auth/login + /auth/verify-login-otp (one hour, every scope — it is the app). Keys are hashed at rest; a lost key is revoked, not recovered.
Scopes
| Scope | Opens |
|---|---|
read | Read shipments, packages, consolidations, tracking, profile, recipients, pre-alerts |
quotes | Price a hypothetical shipment and read public rates |
shipments:write | Book shipments and create pre-alerts |
recipients:write | Create recipients |
invoices | Read bills and payment state |
payments:write | Start a payment for a bill |
deliveries | Read last-mile delivery status |
webhooks | Manage webhook subscriptions |
A call the key is not scoped for answers 403 with errors.required_scope.
Sandbox
Create a key with Test Key ticked. It is prefixed rfp_test_, reads your own shipments, bills and tracking, and on POST /shipments or POST /payments answers 201 with "sandbox": true and a simulated reference — nothing is saved, nothing is charged. Webhooks created with a test key may use http and receive test events only ("sandbox": true in the body); live endpoints must be https and never receive test events.
Rate Limits
Default 60 requests per minute per key (sliding window). Every response carries X-RateLimit-Limit and X-RateLimit-Remaining; past the limit you get 429 with Retry-After. Need more? Ask support — limits are set per key.
Responses
{"status":"success","code":200,"message":"…","data":{…},"meta":{…}}
{"status":"error","code":422,"message":"…","errors":{"field":"why"}}
Lists take ?page=1&per_page=25 (max 100) and return meta.total.
Authentication
/auth/register
Start a customer registration (OTP sent).
{"fname":"Ama","lname":"Mensah","email":"ama@example.com","phone":"0244000000","password":"…"}
/auth/verify-register-otp
Finish registration with the OTP.
{"email":"ama@example.com","otp":"123456"}
/auth/login
Start a login (OTP sent).
{"username":"ama","password":"…"}
/auth/verify-login-otp
Finish login; returns a JWT (1 hour).
{"username":"ama","otp":"123456"}
/auth/me
The caller's account.
Quotes & Rates
/quotes
Price a hypothetical shipment. Indicative — the invoice follows the weight confirmed at the warehouse.
{"mode":"air","items":[{"weight":3,"length":10,"width":8,"height":6,"description":"Phone","declared_value":300}]}
/rates
The public rate cards and the global rate.
Shipments
/shipments
Your shipments (paginated: page, per_page).
/shipments/{id}
One shipment.
/shipments/{id}/tracking
Its tracking events.
/shipments
Book a shipment. mode air|sea|courier; recipient_id optional (must be yours); from{city,state,country,zip,address} optional. Dangerous goods must be booked on the website.
{"mode":"air","recipient_id":845,"items":[{"weight":4,"length":12,"width":10,"height":8,"description":"Laptop","declared_value":800}],"from":{"city":"Houston","state":"TX","country":"United States"}}
/tracking/{reference}
Public tracking by reference.
Packages, Pre-Alerts, Recipients
/packages
Locker packages.
/prealerts
Your pre-alerts.
/prealerts
Register a pre-alert.
{"tracking":"1Z999","provider":"Amazon","courier":"UPS","price":120,"description":"Shoes","date":"2026-08-20"}
/recipients
Your recipients.
/recipients
Create a recipient.
{"fname":"Kofi","lname":"Owusu","phone":"0244111222","email":"kofi@example.com"}
/consolidations
Consolidations your packages ride on.
Invoices & Payments
/invoices
Your bills with paid and balance.
/invoices/{consolidation_id}
One bill, its packages and payments.
/payments
Start a payment. gateway paystack|hubtel|hubtel_direct; amount_ghs defaults to the balance; return_url optional. Returns a checkout_url (or a phone prompt for hubtel_direct).
{"consolidation_id":181,"gateway":"paystack","amount_ghs":250}
/payments/{reference}
The payment's state.
Deliveries
/deliveries/{shipment_id}
Last-mile state: rider, slot, ETA, attempts, proof.
Webhooks
/webhooks
Your endpoints.
/webhooks
Subscribe an https endpoint to events (["*"] for all). The secret is returned once.
{"url":"https://example.com/raptors","events":["shipment.status","payment.received"]}
/webhooks/{id}/test
Send a signed ping now.
/webhooks/{id}/deliveries
The last 100 deliveries and their outcomes.
/webhooks/{id}
Remove an endpoint.
Account
/usage
This key's usage, scopes and limit.
/scopes
The scope and event vocabulary.
/notifications
In-app notifications.
/profile
Your profile.
Webhook Signing
Events: shipment.created shipment.status payment.received bill.issued delivery.updated prealert.created ticket.replied
Every delivery is a JSON POST with headers X-Raptors-Event, X-Raptors-Event-Id, X-Raptors-Timestamp and X-Raptors-Signature: sha256=…. Verify with your secret:
expected = "sha256=" + HMAC_SHA256(secret, timestamp + "." + raw_body) accept only if expected == X-Raptors-Signature and |now - timestamp| < 5 minutes
{"id":"evt_…","event":"shipment.status","created_at":"2026-08-22T07:50:22+00:00","sandbox":false,
"data":{"shipment_id":22771,"reference":"RAP709034","status":"In Warehouse","total_usd":36,"weight":4,"comment":"Received at warehouse","at":"…"}}
Answer 2xx within 15 seconds. Anything else is retried at 1, 5, 25, 125… minutes up to 6 attempts; an endpoint that fails 25 deliveries in a row is switched off until you resume it. Deliveries are at-least-once — use id to de-duplicate.
Try It
—