⌘K

Integration GuidesGuide

Examples

Copyable cURL and TypeScript examples for the current Partner API, webhooks and laboratory contract.

On this page

Setup

bash
export SOLIA_API_BASE="https://app.soliadirect.com/api/public/partner/v1"
export SOLIA_API_KEY="<key>"

Important

There is no Solia SDK. These examples call the HTTP contract directly.

Programs and Catalog

bash
curl -s "$SOLIA_API_BASE/programs" -H "Authorization: Bearer $SOLIA_API_KEY"
curl -s "$SOLIA_API_BASE/programs/$PROGRAM_ID/catalog" -H "Authorization: Bearer $SOLIA_API_KEY"
curl -s "$SOLIA_API_BASE/programs/$PROGRAM_ID/requirements?item_id=$ITEM_ID" -H "Authorization: Bearer $SOLIA_API_KEY"

Serviceability

bash
curl -s -X POST "$SOLIA_API_BASE/serviceability" \
  -H "Authorization: Bearer $SOLIA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"program_id":"'"$PROGRAM_ID"'","item_id":"'"$ITEM_ID"'"}'

Create and simulate a Sandbox order

typescript
const base = process.env.SOLIA_API_BASE!;
const headers = {
  Authorization: `Bearer ${process.env.SOLIA_API_KEY}`,
  "Content-Type": "application/json",
};

export async function createOrder(programId: string, itemId: string, collection: string) {
  const res = await fetch(`${base}/orders`, {
    method: "POST",
    headers: { ...headers, "Idempotency-Key": "order-1001" },
    body: JSON.stringify({
      external_order_id: "order-1001",
      program_id: programId,
      item_id: itemId,
      external_subject_id: "subject-1001",
      collection,
    }),
  });
  const body = await res.json();
  if (!res.ok) throw new Error(`${body.error?.code} (request ${body.request_id})`);
  return body.data;
}

export async function simulate(orderId: string) {
  await fetch(`${base}/sandbox/orders/${orderId}/simulate`, {
    method: "POST",
    headers,
    body: JSON.stringify({ scenario: "happy_path" }),
  });
}

Read order, results and events

bash
curl -s "$SOLIA_API_BASE/orders/$ORDER_ID" -H "Authorization: Bearer $SOLIA_API_KEY"
curl -s "$SOLIA_API_BASE/orders/$ORDER_ID/results" -H "Authorization: Bearer $SOLIA_API_KEY"
curl -s "$SOLIA_API_BASE/events?limit=50" -H "Authorization: Bearer $SOLIA_API_KEY"

Verify a webhook signature

typescript
import { createHmac, timingSafeEqual } from "node:crypto";

const seenDeliveries = new Set<string>();

export function verifySolia(rawBody: string, headers: Record<string, string>, secret: string): boolean {
  const timestamp = Number(headers["x-solia-timestamp"]);
  const presented = headers["x-solia-signature"] ?? "";
  const deliveryId = headers["x-solia-delivery-id"];
  if (!Number.isFinite(timestamp) || Math.abs(Date.now() / 1000 - timestamp) > 300) return false;
  const expected = "v1=" + createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");
  if (expected.length !== presented.length) return false;
  if (!timingSafeEqual(Buffer.from(expected), Buffer.from(presented))) return false;
  if (deliveryId && seenDeliveries.has(deliveryId)) return false;
  if (deliveryId) seenDeliveries.add(deliveryId);
  return true;
}

Use durable storage instead of an in-memory set in production.

HTTPS/JSON laboratory endpoint

Your laboratory server receives POST <your base>/connection-test and POST <your base>/orders with X-Solia-Contract-Version: solia.lab.v1, X-Solia-Tenant-Id, X-Solia-Adapter-Key, X-Solia-Transmission-Id and Idempotency-Key. Respond 2xx within 15 seconds and deduplicate on the idempotency key.

Inbound lifecycle events are POSTed to /api/public/lab-events signed with X-Solia-Signature: v1=<hex HMAC-SHA256> over <X-Solia-Timestamp>.<raw body>. The exact body schema is published at /api/public/solia-lab-contract.

bash
TS=$(date +%s)
SIG="v1=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$LAB_SIGNING_SECRET" -hex | sed 's/^.* //')"
curl -s -X POST "https://app.soliadirect.com/api/public/lab-events" \
  -H "X-Solia-Timestamp: $TS" -H "X-Solia-Signature: $SIG" \
  -H "Content-Type: application/json" --data "$BODY"

Related resources