Skip to main content

Quickstart

This quickstart takes you from a new test account to a booked delivery. You will save two addresses, get a quote and book it. Nothing here costs money or sends a rider.

The cURL steps use jq to keep the token and ids in shell variables, so each step can use the one before it.

1. Create a test account​

Sign up and verify your email and phone number. Your account opens in Test mode, with a ₦100,000 test wallet ready.

2. Copy your test credentials​

In the dashboard, make sure the switch in the header says Test, then open Developers and create your credentials. Copy the client id (rci_test_...) and the client secret (rcs_test_...). The secret is shown once.

Put them in environment variables on your machine:

export REEDS_CLIENT_ID="rci_test_xxxxxxxxxxxx"
export REEDS_CLIENT_SECRET="rcs_test_xxxxxxxxxxxx"

3. Get an access token​

Exchange the credentials for an access token. A token lasts one hour. See Authentication for caching.

export REEDS_ACCESS_TOKEN=$(curl -s https://api.getreeds.co/oauth/token \
-d grant_type=client_credentials \
-d client_id="$REEDS_CLIENT_ID" \
-d client_secret="$REEDS_CLIENT_SECRET" | jq -r .access_token)
Response 200
{
"access_token": "eyJhbGciOi...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "shipping",
"livemode": false
}

The examples below read the token from REEDS_ACCESS_TOKEN. Every response has "status": "success" and your result in data.

Running the Node.js, PHP and Python examples

Each example runs on its own. Save a Node.js example as a .mjs file and run it with Node 18 or later. A token set in code lasts only for that run, so to follow along, export REEDS_ACCESS_TOKEN in your shell as the cURL tab does. In your app, keep the token in a variable.

4. Save the pickup address​

Send a map pin as well as the text, so the outcome is predictable: Reeds trusts latitude and longitude, so this one comes back verified and serviceable in Ikeja.

PICKUP_ID=$(curl -s https://api.getreeds.co/shipping/v1/addresses \
-H "Authorization: Bearer $REEDS_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Ada Okafor",
"phone": "08031234567",
"address": "23 Allen Avenue, Ikeja, Lagos",
"latitude": 6.6018,
"longitude": 3.3515
}' | jq -r .data.id)
echo "$PICKUP_ID"
Response 201 (trimmed)
{
"status": "success",
"data": {
"id": "adr_7Hq2Lk9P",
"livemode": false,
"status": "verified",
"serviceable": true,
"contact": { "name": "Ada Okafor", "phone": "08031234567", "email": null },
"location": { "lga": "Ikeja", "state": "Lagos", "country": "NG" }
}
}

5. Save the drop-off address​

DROPOFF_ID=$(curl -s https://api.getreeds.co/shipping/v1/addresses \
-H "Authorization: Bearer $REEDS_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Chidi Eze",
"phone": "08098765432",
"address": "14 Admiralty Way, Lekki, Lagos",
"latitude": 6.4474,
"longitude": 3.4723
}' | jq -r .data.id)
echo "$DROPOFF_ID"
Response 201 (trimmed)
{
"status": "success",
"data": {
"id": "adr_5Vb1Jc8D",
"livemode": false,
"status": "verified",
"serviceable": true,
"contact": { "name": "Chidi Eze", "phone": "08098765432", "email": null },
"location": { "lga": "Lekki", "state": "Lagos", "country": "NG" }
}
}

To reach the other outcomes (needs confirmation, not serviceable, inter-state), see Test addresses.

6. Get a quote​

Send both address ids and the package. Use the id values from steps 4 and 5: the ids on this page are examples and won't work on your account. Money is in kobo, so 280000 is ₦2,800. Your price will differ from this example, because it depends on the road distance.

BODY=$(jq -n --arg pickup "$PICKUP_ID" --arg dropoff "$DROPOFF_ID" '{
pickup_address_id: $pickup,
dropoff_address_id: $dropoff,
package: {
description: "2 pairs of sneakers",
quantity: 1,
weight_kg: 1.5,
declared_value: 4500000
}
}')

QUOTE_ID=$(curl -s https://api.getreeds.co/shipping/v1/quotes \
-H "Authorization: Bearer $REEDS_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d "$BODY" | jq -r .data.id)
echo "$QUOTE_ID"
Response 201 (trimmed)
{
"status": "success",
"data": {
"id": "qt_2bX9Wn4K",
"available": true,
"livemode": false,
"expires_at": "2026-10-27T10:20:00+01:00",
"service": "standard",
"route": { "type": "via_hub", "distance_km": 13.5 },
"fee": {
"delivery_fee": 255000,
"vat": 19125,
"service_charge": 5875,
"discount": 0,
"total": 280000,
"currency": "NGN"
},
"schedule": {
"pickup_by": "2026-10-26T19:00:00+01:00",
"deliver_by": "2026-10-27T19:00:00+01:00",
"earliest_delivery": "2026-10-26T19:00:00+01:00"
}
}
}

The quote is valid for 24 hours and books one delivery. If available is false, the response gives a reason instead of a price. See Quotes.

7. Book the delivery​

Book with the quote id. Booking needs an Idempotency-Key header, which makes a retry safe: the same key with the same body returns the original delivery and never books twice. Use a key that identifies the attempt, such as order-10045-delivery-1.

BODY=$(jq -n --arg quote "$QUOTE_ID" '{
quote_id: $quote,
reference: "ORDER-10045",
dropoff_instructions: "Call on arrival"
}')

curl https://api.getreeds.co/shipping/v1/deliveries \
-H "Authorization: Bearer $REEDS_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-10045-delivery-1" \
-d "$BODY"
Response 201 (trimmed)
{
"status": "success",
"data": {
"id": "dlv_9Kd3Qx7M",
"livemode": false,
"reference": "ORDER-10045",
"status": "scheduled",
"required_actions": [],
"cancellable": true,
"tracking_code": "HQ3W5F2",
"tracking_url": "https://getreeds.co/packages/HQ3W5F2",
"fee": {
"total": 280000,
"currency": "NGN",
"status": "charged",
"billing": "wallet"
},
"schedule": {
"pickup_by": "2026-10-26T19:00:00+01:00",
"deliver_by": "2026-10-27T19:00:00+01:00"
}
}
}

Your test wallet was debited the quote's fee.total and the delivery is scheduled.

If you run this step again with a new quote, change the key too (for example order-10045-delivery-2). The same key with a different body gets 422 IDEMPOTENCY_KEY_REUSED.

What happens next​

  • Tracking. tracking_url is a public page you can send to your customer. It shows progress without a login.
  • Webhooks. Set a webhook endpoint for Test mode in Dashboard → Developers. Reeds then sends delivery.created and delivery.booked, then a delivery.status_changed for each status until delivered. See Webhooks.
  • Test deliveries don't move by themselves. Move yours along with the sandbox endpoints. See Sandbox.
  • Changed your mind? You can cancel while the delivery's cancellable is true, until the rider sets off for the pickup. See Cancellations.
Something failed?

Branch on the HTTP status and error.code, never on the message. Common first-run errors are INSUFFICIENT_BALANCE (fund the test wallet) and QUOTE_EXPIRED (quote again). See Errors.

Next steps​