DEV Community

Cover image for Create your first delivery task with Relay (Node, test mode)
SendRelay for SendRelay

Posted on

Create your first delivery task with Relay (Node, test mode)

Create your first delivery task with Relay (Node, test mode)

New to Relay? Start with the story behind it.

Imagine you run a pharmacy app in Lagos. An order is packed, but your checkout has no delivery ID to show the customer. Your team could call riders one by one and answer “where is my order?” from a chat thread. Instead, your backend can hand the delivery to Relay when the order is ready, save the task ID, and use that ID to follow its progress. In test mode, you can build that handoff without dispatching a real rider.

In this tutorial, you'll create a simulated package delivery with Relay's Node SDK. You'll install the SDK, use a test API key, send pickup and dropoff stages, and retrieve the task you created. The same pattern gives your order system a stable reference for later webhook handling.

What you'll build

This is the core call. It creates a test task with a deliberate idempotency key, so a retry for the same order does not create another intended delivery:

import { RelayClient } from '@relay-sdk/sdk-node';

const relay = new RelayClient({ apiKey: process.env.RELAY_API_KEY });

const created = await relay.tasks.create(
  {
    taskType: 'PACKAGE_DELIVERY',
    simulationOutcome: 'SUCCESS',
    autoAssign: true,
    stages: [
      {
        type: 'PICKUP',
        location: {
          latitude: 6.5244,
          longitude: 3.3792,
          address: 'Demo pickup, Lagos',
        },
        instructions: 'Simulation only',
        items: [
          {
            name: 'Demo parcel',
            estimatedValue: 100000,
            estimatedWeight: 'STANDARD',
            estimatedSize: 'BOX',
          },
        ],
      },
      {
        type: 'DROPOFF',
        location: {
          latitude: 6.4654,
          longitude: 3.4064,
          address: 'Demo dropoff, Lagos',
        },
        instructions: 'Simulation only',
      },
    ],
  },
  { idempotencyKey: 'order-demo-001-delivery' },
);

console.log(created.task.taskId, created.task.status);
Enter fullscreen mode Exit fullscreen mode

The coordinates and addresses above are demonstration inputs. estimatedValue is the parcel's declared value in kobo; it is not a delivery quote. Relay's create-task guide covers the request fields in detail.

Get a test key

Create a Relay account and get an API key. Use a key that starts with sk_test_; the current SDK and API-key guide use that prefix for test mode. Keep the key on your server and out of source control. Never put it in browser code.

For a local Node project, install the SDK and put your key in your shell environment:

npm install @relay-sdk/sdk-node
export RELAY_API_KEY='sk_test_YOUR_TEST_KEY'
Enter fullscreen mode Exit fullscreen mode

The placeholder is not a real credential. If you use another shell or hosting platform, set the environment variable through its secret settings. The SDK sends the key in the X-Relay-Key header; you do not need to build that header yourself.

Create the task

Save the first code block as create.mjs, then run:

node create.mjs
Enter fullscreen mode Exit fullscreen mode

Use Node 18 or newer, as required by the Node SDK. A successful call prints the task ID and its initial status. Save created.task.taskId against your own order ID. Task creation means the delivery request was accepted; it does not mean delivery is complete.

The request has two stages. PICKUP tells Relay where the parcel begins; DROPOFF tells it where the parcel should end. simulationOutcome: 'SUCCESS' selects the success path for a test task. Test mode simulates the lifecycle without a real rider or real payment. You can use simulation outcomes to exercise other branches after the basic path works.

The second argument to relay.tasks.create() sets idempotencyKey. Derive this from a stable order ID in your app. If a network timeout makes you uncertain whether the create succeeded, retry the same intended delivery with the same key. For a different order, use a different key. The SDK can generate a key automatically, but an explicit order-based key gives your application control over retries.

Do not add paymentMethod: 'TEST' to this request. The test key selects the test flow. When you build your real order workflow, review the task creation guide and your payment setup before switching to a live key.

Read the task back

The task ID is the link between your order and Relay's delivery state. Add this after the create call to fetch the task:

const latest = await relay.tasks.get(created.task.taskId);
console.log('task' in latest ? latest.task.status : latest.status);
Enter fullscreen mode Exit fullscreen mode

A test simulation can progress after the create response, so the status you read immediately may still be an early lifecycle state. Store the ID, then use task retrieval when you need the current snapshot. The Node SDK guide describes the task methods and response shape.

For an application that must update a customer or operations screen when the status changes, subscribe to Relay's webhook events. Verify each webhook's signature against the raw request body before using its data, and make event handling safe to repeat. Your order database should record the Relay task ID and the event IDs it has already processed. This is how the same Lagos order can move from “ready” to a delivery state your team can inspect without manual rider calls.

Build the next slice

Once the success simulation works, create a new test order using simulationOutcome: 'NO_RIDERS'. Decide what your checkout and support team should see when there is no available rider. Then connect the webhook to your order state and test duplicate delivery of an event before you use a live key.

You now have a small, repeatable delivery integration: an order triggers one Relay task, your app saves its ID, and you can inspect its status. Get your test API key and follow the first-request guide to try it in your backend.

Cover photo by @ib_daye on Unsplash.

Top comments (0)