Skip to content
Track That Ride
Menu

Quickstart

Node.js quickstart

This Node.js quickstart creates a delivery through the Track That Ride API, prints the customer’s live tracking link and lists your recent deliveries, then shows a webhook receiver that verifies signatures. It uses only Node 18’s built-in fetch, http and crypto modules, so there is nothing to install.

Before you start

  1. Sign up and create an API key under API keys with rides:read and rides:write.
  2. Set it as an environment variable: export TTR_API_KEY="tk_live_..."
  3. Save the script below as create-delivery.mjs.

Create a delivery and print its tracking link

// Create a delivery with the Track That Ride API and print the customer's tracking link.
// Node.js 18+ (built-in fetch). Usage:
//   TTR_API_KEY=tk_live_... node create-delivery.mjs
const API = 'https://trackthatride.com/api/v1';
const key = process.env.TTR_API_KEY;
if (!key) throw new Error('Set TTR_API_KEY to an API key with rides:read and rides:write');

async function ttr(path, options = {}) {
  const res = await fetch(`${API}${path}`, {
    ...options,
    headers: { Authorization: `Bearer ${key}`, 'Content-Type': 'application/json', ...options.headers },
  });
  const body = await res.json().catch(() => ({}));
  if (!res.ok) {
    // Errors carry `error`, and usually `code` (branch on it) and `message`.
    throw new Error(`${res.status} ${body.code ?? body.error ?? ''}: ${body.message ?? JSON.stringify(body)}`);
  }
  return body;
}

// Pickup in two hours; estimated_pickup_time must be in the future.
const pickupAt = new Date(Date.now() + 2 * 60 * 60 * 1000).toISOString();

const ride = await ttr('/rides', {
  method: 'POST',
  body: JSON.stringify({
    customer_name: 'Jane Example',
    phone_number: '07700 900123',
    email: 'jane@example.com', // the customer is emailed the tracking link
    address: '10 Downing Street, London SW1A 2AA',
    pickup_address: '1 Example Road, London E1 6AN',
    pickup_contact_name: 'Front desk',
    pickup_phone: '07700 900456',
    estimated_pickup_time: pickupAt,
    order_id: 'ORDER-1001',
  }),
});

console.log(`Created delivery ${ride.id} (${ride.status})`);
console.log(`Tracking link: https://trackthatride.com/track/${ride.public_tracking_token}`);

// List the five most recent deliveries.
const { rides, pagination } = await ttr('/rides?limit=5&sortBy=created_at&sortOrder=desc');
console.log(`Total: ${pagination.total}. Latest:`);
for (const r of rides) console.log(`  #${r.id} ${r.status.padEnd(11)} ${r.customer_name}`);

Run it with node create-delivery.mjs. You should see something like:

Created delivery 123 (pending)
Tracking link: https://trackthatride.com/track/AbC...xyz
Total: 14. Latest:
  #123 pending     Jane Example

Errors are thrown with the status and the API’s code, for example 401 Invalid API key or 403 Insufficient permissions. The delivery stays pending until a driver is assigned, which you can do in the dashboard or with POST /api/v1/rides/{id}/assign-driver.

Receive and verify webhooks

Register a webhook (see webhooks) and keep the secret from the response. This server checks the X-Webhook-Signature header against an HMAC-SHA256 of the raw body before trusting anything in it:

// Receive and verify Track That Ride webhooks. Node.js 18+, no dependencies.
// Usage: TTR_WEBHOOK_SECRET=whsec_... node webhook-receiver.mjs
// Then register https://<your-host>/hooks/ttr with POST /api/v1/webhooks.
import crypto from 'node:crypto';
import http from 'node:http';

const SECRET = process.env.TTR_WEBHOOK_SECRET;
if (!SECRET) throw new Error('Set TTR_WEBHOOK_SECRET to the secret returned when you created the webhook');

function verify(rawBody, header) {
  const expected = 'sha256=' + crypto.createHmac('sha256', SECRET).update(rawBody).digest('hex');
  const received = String(header ?? '');
  return received.length === expected.length && crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected));
}

http
  .createServer((req, res) => {
    if (req.method !== 'POST' || req.url !== '/hooks/ttr') {
      res.writeHead(404).end();
      return;
    }
    const chunks = [];
    req.on('data', (c) => chunks.push(c));
    req.on('end', () => {
      const raw = Buffer.concat(chunks); // sign-check the raw bytes, before parsing
      if (!verify(raw, req.headers['x-webhook-signature'])) {
        res.writeHead(401).end();
        return;
      }
      let event;
      try {
        event = JSON.parse(raw.toString('utf8'));
      } catch {
        res.writeHead(400).end(); // signed but not JSON: reject instead of crashing the process
        return;
      }
      res.writeHead(200).end(); // answer in under 30 seconds; do slow work afterwards
      console.log(`${event.event_type} ride ${event.ride_id}: ${event.data?.status ?? ''}`);
      if (event.event_type === 'delivery.completed') {
        console.log(`  delivered; tracking page https://trackthatride.com/track/${event.tracking_code}`);
      }
    });
  })
  .listen(3000, () => console.log('Listening on http://localhost:3000/hooks/ttr'));

What we tested

These scripts are kept in the examples/node folder of our repository and run against the live API: a request with an invalid key returns the API’s 401 error, and the receiver accepts a correctly signed request and rejects a bad signature.

Frequently asked questions

Which Node.js version do I need?

Node.js 18 or later, for the built-in fetch. Nothing else is required.

Can I use the @trackthatride/core package instead?

Yes. @trackthatride/core 2.0.1 wraps the same calls (createRide, getRides, getRide, updateRide) and returns the API’s own fields; see Using the SDK on the developer hub. These examples call the API directly so you can see every request, and are short enough to copy into any project.

How do I test the webhook receiver locally?

Run it, expose port 3000 with a tunnelling tool of your choice, register the public URL with POST /api/v1/webhooks, then call POST /api/v1/webhooks/{id}/test to send a webhook.test event.

Does creating a test delivery cost anything?

No. Billing counts deliveries that are started by a driver. A delivery you create and then cancel is not charged.

Get an API key

Sign up free with no card, create a key under API keys, and run this example against your own account.

Sign-up happens on trackthatride.com.