Gareth Wilson Gareth Wilson

Guide to Firstbase Webhooks: Features and Best Practices

Published


Firstbase webhooks tell your systems when equipment moves. A laptop order is created, needs approval, ships or is delivered; a returned kit arrives back at the processing facility; an inventory order item is received. If you equip remote employees through Firstbase, webhooks let your HRIS, IT asset register and onboarding workflows react to those changes instead of polling the Firstbase API.

This guide covers how Firstbase webhooks are configured, why their payloads carry only IDs, how to authenticate them with a custom header, and the timeout and retry rules your receiver has to meet.

What are Firstbase webhooks?

Each Firstbase webhook covers one resource type: orders, return orders or inventory orders. You choose which events in that category trigger it, and optionally filter by region or destination. When a matching event happens, Firstbase sends a JSON POST to your HTTPS URL.

The payload is deliberately thin. It says which resource changed and whether it was created, updated or deleted, but not which granular event fired. Your receiver fetches the resource from the Firstbase API to find out its current status.

Firstbase doesn't sign webhooks. A webhook can authenticate to your endpoint with no headers, an auth token, a custom header, or OAuth client credentials. For a receiver that checks a static secret, choose Custom header: you set both the header name and its value, so you know exactly what to compare.

Firstbase webhook features

FeatureDetails
ConfigurationAPI & Integrations > Webhooks > Add Webhook (admin permissions)
Resource typesOrder events, Return order events, Inventory order events
FiltersRegion or country. Destination type for orders, return destination for returns
Method and formatPOST, JSON
PayloadeventId, eventType, resourceType, resourceId
AuthenticationNone, Auth token, Custom header or OAuth client credentials. No signature
Timeout10 seconds
Success200, 201, 202 or 204
RetriesUp to 12 attempts over about 2 to 3 hours, backoff up to 1 hour apart
After retriesMarked failed. Resend manually from the Activity tab
Delivery history90 days, with request, response and status code
LimitsNo limit on webhooks. One webhook per URL and resource type

Common events

Resource typeEvents you can select
OrdersCreated, requires approval, shipped, delivered, delivery exception, cancelled
Return ordersSubmitted, confirmed, cancelled, completed, marked as not returned, kit sent, kit sent back, arrived at processing facility
Inventory ordersCreated, item shipped, item received, item delivery exception, item cancelled, shipment item cancelled, cancelled, arrived at processing facility

These selections decide whether Firstbase sends a notification. They aren't in the payload. Every notification looks like this:

{
  "eventId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "eventType": "UPDATED",
  "resourceType": "ORDER",
  "resourceId": "550e8400-e29b-41d4-a716-446655440000"
}
  • eventId is unique per event. Firstbase says the same event may be delivered more than once during retries, so use it to deduplicate.
  • eventType is CREATED, UPDATED or DELETED.
  • resourceType is ORDER, RETURN_ORDER or INVENTORY_ORDER.
  • resourceId is the order, return or inventory order to fetch.

To tell a shipped order from a delivered one, fetch it and read its status: GET /api/v1/orders/{orderId}, GET /api/v1/returns/{returnId} or GET /api/v1/inventory-orders/{inventoryOrderId}.

The Test button sends a different body, {"type": "webhook.test", "timestamp": "..."}, so make sure your receiver acknowledges it rather than rejecting a body with no eventId.

Inspect Firstbase webhooks as they arrive. Point a webhook at a Hookdeck Inspect URL and click Test to see the body and headers Firstbase sends, with no account or setup required.

Setting up Firstbase webhooks

Pick a header name, such as Authorization or X-Firstbase-Secret, and generate a long random value, for example with openssl rand -hex 32.

  1. Go to API & Integrations and click Webhooks.
  2. Click Add Webhook.
  3. Enter a Name and choose the Resource Type.
  4. Leave All events on, or turn it off and select specific events.
  5. Enter the HTTPS Target URL.
  6. Under Authentication, choose Custom header and enter the header name and value.
  7. Apply any region or destination filters, then click Add Webhook.
  8. Make sure the webhook's toggle is on, and click Test.

To cover orders, returns and inventory orders on one URL, create three webhooks, one per resource type. Firstbase won't create two webhooks with the same URL and resource type.

To route through Hookdeck, create a source with the Firstbase type and use its URL in step 5. Enter the header name in API Key Header and the exact value, including any Bearer prefix, in API Key. As Hookdeck's setup note says, use Custom header authentication, not Auth token or OAuth: Firstbase doesn't document which header Auth token sends, and OAuth client credentials need a token server that issues access tokens. The source accepts POST.

Securing Firstbase webhooks

Look up the header you configured and compare its whole value with the stored secret, in constant time.

const crypto = require('crypto');
const express = require('express');

const HEADER_NAME = (process.env.FIRSTBASE_WEBHOOK_HEADER || 'authorization').toLowerCase();
const EXPECTED = process.env.FIRSTBASE_WEBHOOK_SECRET;

function safeEqual(received, expected) {
  const a = Buffer.from(received, 'utf8');
  const b = Buffer.from(expected, 'utf8');
  // timingSafeEqual throws on unequal lengths, so check first.
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

const app = express();

app.post('/webhooks/firstbase', express.raw({ type: '*/*' }), (req, res) => {
  const received = req.get(HEADER_NAME);
  if (!EXPECTED || typeof received !== 'string' || !safeEqual(received, EXPECTED)) {
    return res.sendStatus(401);
  }

  let event;
  try {
    event = JSON.parse(req.body.toString('utf8'));
  } catch {
    return res.sendStatus(400);
  }
  if (event.type === 'webhook.test') return res.sendStatus(200);

  // Store event.eventId, queue a job to fetch event.resourceType / event.resourceId,
  // and respond within 10 seconds.
  res.sendStatus(200);
});

The same check in Python:

import hmac
import os

HEADER_NAME = os.environ.get("FIRSTBASE_WEBHOOK_HEADER", "Authorization")
EXPECTED = os.environ.get("FIRSTBASE_WEBHOOK_SECRET", "")


def verify_firstbase_request(headers) -> bool:
    if not EXPECTED:
        return False  # never accept when unconfigured
    received = headers.get(HEADER_NAME)  # most frameworks look headers up case-insensitively
    if not received:
        return False
    # Compare bytes: compare_digest raises TypeError on a non-ASCII str.
    return hmac.compare_digest(received.encode("utf-8"), EXPECTED.encode("utf-8"))

A static header authenticates the sender, not the body. It cannot show that a payload wasn't modified, and with no timestamp a captured request can be replayed and still pass. The thin payload limits the damage: a forged notification can only make you fetch a resource, and the data you act on comes from the authenticated Firstbase API. Still, use HTTPS, a long random value, and change it in the webhook settings if it might have leaked.

Make Firstbase webhooks production-ready. Hookdeck Event Gateway checks your custom header, answers Firstbase inside its 10-second timeout, and queues every notification durably while your service fetches the details.

Firstbase webhook limitations and pain points

The payload doesn't say what happened

The Problem: You subscribed to "order shipped" and "order delivered", and both arrive as UPDATED on an ORDER.

Why It Happens: Firstbase sends only IDs and a coarse eventType, so the receiver gets the current data from the API rather than from the webhook.

Workarounds:

  • Fetch the resource for every notification and act on its current status.
  • Select only the granular events you act on, so you fetch fewer resources you would discard.

How Hookdeck Can Help: Hookdeck queues notifications and delivers them at a max delivery rate, so fetching every resource doesn't overload your service or the Firstbase API. See handling thin events with Hookdeck.

Ten seconds, then a retry

The Problem: A handler that calls the Firstbase API before responding times out and receives the same event again.

Why It Happens: Firstbase waits 10 seconds for a 2xx. A timeout, 4xx or 5xx triggers retries: up to 12 attempts over 2 to 3 hours, at 5, 10, 20 and 40 seconds and growing to an hour apart.

Workarounds:

  • Store the notification and respond first, then fetch the resource in a background job.
  • Deduplicate on eventId.

How Hookdeck Can Help: Hookdeck answers Firstbase as soon as a notification arrives and delivers it to your service with a delivery timeout you choose, so slow fetches no longer cause Firstbase retries.

Retries end after a few hours

The Problem: An outage longer than an afternoon leaves notifications marked as failed.

Why It Happens: After 12 attempts, Firstbase stops and waits for someone to click Resend in the Activity tab, which keeps 90 days of history.

Workarounds:

  • Watch the Activity tab's Failed filter after incidents and resend.
  • Reconcile open orders and returns against the API periodically.

How Hookdeck Can Help: Hookdeck's ingestion stays up when your service is down, so Firstbase's deliveries succeed. Hookdeck then retries delivery to your service on your schedule, and you can replay any notification.

Authentication options that don't fit a static check

The Problem: You pick Auth token or OAuth client credentials and can't tell what your receiver should compare.

Why It Happens: Firstbase says Auth token "sends a bearer/token value you provide" without naming the header, and with OAuth client credentials Firstbase requests an access token from your token URL and uses it when delivering events.

Workarounds:

  • Use Custom header, which sends a header name and value you choose.

How Hookdeck Can Help: Hookdeck's Firstbase source checks the custom header you configure. Hookdeck answers Firstbase with a 200 either way, but a request with a missing or wrong header is recorded as failed verification and never reaches your service.

Best practices

Fetch, don't trust

Treat each notification as a pointer. Fetch the resource from the Firstbase API and act on what it returns.

Deduplicate on eventId

Firstbase says retries can deliver the same event twice. Store eventId before processing. See our guide to webhook idempotency.

Handle the test body

Acknowledge {"type": "webhook.test"} with a 2xx and do nothing else.

Use filters at the source

Region and destination filters cut notifications you would otherwise fetch and discard.

Acknowledge fast and process asynchronously

Ten seconds isn't enough for an API call chain. See why to process webhooks asynchronously.

Conclusion

Firstbase sends thin JSON notifications for orders, returns and inventory orders, authenticated by whatever you choose under Authentication. Choose Custom header, compare it whole in constant time, deduplicate on eventId, fetch each resource for its real status, and respond within 10 seconds.

Hookdeck Event Gateway checks the header, answers Firstbase immediately, and paces delivery so your service can fetch details at its own speed.

Get started with Hookdeck for free and handle Firstbase webhooks reliably in minutes.


Gareth Wilson

Gareth Wilson

Product Marketing

Multi-time founding marketer, Gareth is PMM at Hookdeck and author of the newsletter, Community Inc.