Docs Getting started Quick start
Quick start

Zero to verified chain
in under ten minutes.

By the end of this guide you will have created a chain, generated confirmation links for three actors, and verified the completed audit trail. No configuration beyond an API key.

Under 10 minutes
1
Install the SDK

The SwiftProof JavaScript SDK is published on npm. Install it in your project.

terminal
npm install swiftproof
TypeScript types are included. No separate @types/swiftproof package needed.
2
Get your API key

Email hello@tryswiftproof.com with your project name and use case. We will provision your API key and project within one business day.

Store your API key in an environment variable. Never commit it to version control.

.env
SWIFTPROOF_API_KEY=sp_live_your_key_here
Never expose your API key client-side. All SwiftProof API calls must be made from your backend. The SDK is designed for server-side use.
3
Create your first chain

A chain is a sequence of steps that need to happen in order. Each step has an actor responsible for confirming it. Define the steps, call chains.create(), and you get back a confirmation link for each actor and a tracking link for the end customer.

create-chain.js
import { SwiftProof } from 'swiftproof';

const sp = new SwiftProof({
  apiKey: process.env.SWIFTPROOF_API_KEY,
});

const chain = await sp.chains.create({
  title: 'Order #4821 — Delivery to Lekki Phase 1',
  metadata: {
    orderId: '4821',
    customerPhone: '08012345678',
  },
  actors: [
    { event: 'packed',    actor: 'Kitchen — Surulere' },
    { event: 'collected', actor: 'Rider — Emeka'      },
    { event: 'delivered', actor: 'Rider — Emeka'      },
  ],
});

console.log(chain);

The response contains a confirmation URL for each actor and a tracking URL for the customer.

response
{
  "chain_id":     "sp_ch_a96fec076ffd44f4",
  "status":       "open",
  "tracking_url": "https://proof.tryswiftproof.com/track/abc123",
  "handoffs": [
    {
      "event":            "packed",
      "actor":            "Kitchen — Surulere",
      "confirmation_url": "https://proof.tryswiftproof.com/confirm/tok_001",
      "expires_at":       "2026-06-26T08:14:00Z"
    },
    {
      "event":            "collected",
      "actor":            "Rider — Emeka",
      "confirmation_url": "https://proof.tryswiftproof.com/confirm/tok_002",
      "expires_at":       "2026-06-26T08:14:00Z"
    },
    {
      "event":            "delivered",
      "actor":            "Rider — Emeka",
      "confirmation_url": "https://proof.tryswiftproof.com/confirm/tok_003",
      "expires_at":       "2026-06-26T08:14:00Z"
    }
  ]
}
Field Type Description
chain_id string Unique identifier. Save this — you will use it to verify later.
status string open until all actors confirm. Then completed.
tracking_url string Share with the end customer. Shows real-time progress. No app required.
handoffs[].confirmation_url string Send to the actor via WhatsApp or SMS. One-time use.
handoffs[].expires_at string ISO 8601 timestamp. Link expires after 48 hours by default.
4
Send the links to each actor

Distribute each confirmation URL to the relevant actor. The confirmation page works in any mobile browser. No app required. No login required.

distribute-links.js
// Send to kitchen via WhatsApp
await sendWhatsApp(
  kitchenNumber,
  `Order #4821 is ready to pack.\nConfirm here: ${chain.handoffs[0].confirmation_url}`
);

// Send to rider
await sendWhatsApp(
  riderPhone,
  `Collect order #4821.\nConfirm collection and delivery here: ${chain.handoffs[1].confirmation_url}`
);

// Send tracking link to customer
await sendSMS(customerPhone, `Track your order: ${chain.tracking_url}`);

// Save chain_id to your database
await db.orders.update({ id: orderId, swiftproofChainId: chain.chain_id });
Each confirmation URL is one-time use. Once an actor confirms, the link is consumed. Failed attempts and expired links are logged in the audit trail automatically.
5
Verify the chain

Call chains.verify() with the chain_id at any point. The response tells you whether the chain is verified, whether it has been tampered with, and the full audit trail with GPS coordinates and timestamps for every step.

verify-chain.js
const proof = await sp.chains.verify('sp_ch_a96fec076ffd44f4');

if (proof.tampered) {
  console.error('Chain has been tampered with');
  return;
}

for (const step of proof.trail) {
  console.log(step.event, step.confirmed_at, step.location, step.valid);
}
response
{
  "verified": true,
  "tampered": false,
  "trail": [
    { "event": "packed",    "actor": "Kitchen — Surulere", "confirmed_at": "2026-06-24T08:14:00Z", "location": "Ogunlana Drive, Surulere, Lagos", "valid": true },
    { "event": "collected", "actor": "Rider — Emeka",      "confirmed_at": "2026-06-24T08:47:00Z", "location": "Ogunlana Drive, Surulere, Lagos", "valid": true },
    { "event": "delivered", "actor": "Rider — Emeka",      "confirmed_at": "2026-06-24T09:22:00Z", "location": "Admiralty Way, Lekki Phase 1, Lagos", "valid": true }
  ]
}
That is it. You created a chain, distributed confirmation links, and verified a complete tamper-proof audit trail. Three API calls. Under ten minutes.
6
Handle retries safely

Pass an Idempotency-Key header on every chain creation call to ensure retries never create duplicate chains.

idempotent-create.js
const chain = await sp.chains.create({
  title: 'Order #4821',
  actors: [...],
}, {
  idempotencyKey: `order-4821-chain`,
});

// Safe to retry on network failure.
// If the key already exists, the original response is returned.
What is next

Keep building.

You have the foundation. Here is where to go next.