Skip to main content

Automations

Put refunds to work in the tools you already use.

Three ways in, one set of rules. Your AI assistant, your apps and your other systems see the same cases, and nothing skips your approvals.

  • MCP server

    Let an AI assistant read cases and propose decisions over the Model Context Protocol.

    Set up MCP
  • Public API

    Four operations to open, list, read and update refund cases with a workspace API key.

    See the API
  • Webhooks

    13 signed event types pushed to your endpoint, retried and replayable.

    See webhooks

Public API

Open a case from your own code.

A small, stable surface for cases, authenticated with a workspace API key. The reference is served by your API at /public/v1/docs.

Operations
MethodPathScopeWhat it does
POST/public/v1/refund-casesintakeOpen a refund case. A duplicate key returns the original case with 200.
GET/public/v1/refund-casesreadList your workspace's cases.
GET/public/v1/refund-cases/{id}readRead one case with its state and items.
POST/public/v1/refund-cases/{id}/return-receivedintakeRecord that the return arrived.
Sample data
Request
curl -X POST https://<api-host>/public/v1/refund-cases \
  -H "Authorization: Bearer eqk_live_…" \
  -H "Idempotency-Key: ord-10442-refund-1" \
  -H "Content-Type: application/json" \
  -d '{
    "external_order_id": "10442",
    "amount_minor": 4999,
    "currency": "USD",
    "reason": "Arrived damaged",
    "line_items": [{ "line_id": "li_1", "quantity": 1 }],
    "order_country": "US"
  }'
Response
HTTP/1.1 201 Created
X-Correlation-ID: 7c1e9a52-3b0f-4d8e-9a61-2f5c0b7d4e13
X-RateLimit-Remaining: 1199

{
  "refund_case_id": "01J9Z3K4M8Q2V6X0B5N7T1R3Y8",
  "state": "RECEIVED",
  "external_order_id": "10442",
  "amount_minor": 4999,
  "currency": "USD",
  "created_at": "2026-09-24T14:02:11Z"
}

Conventions

  • Idempotency-Key on every POST, kept for 24 hours. A reused key with a different body returns 409.
  • X-Correlation-ID is echoed back, or generated for you, on every response.
  • Errors share one shape: error.code, error.message and the correlation id.
  • X-RateLimit headers on every response. Plan ceilings: Free 120, Starter 600, Growth 1,200 and Scale 2,400 requests per minute.

Webhooks

Every event, signed and retried.

Owners and Admins add endpoints in the dashboard. Each delivery is signed, sequenced and retried at 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours before it is dead-lettered and can be replayed.

Refund cases

  • refund_case.created
  • refund_case.state_changed
  • refund_case.approved
  • refund_case.denied
  • refund_case.refund_executed
  • refund_case.completed
  • refund_case.failed
  • refund_case.return_received

Approvals

  • approval.requested
  • approval.decided

Labels and agents

  • return_label.purchased
  • agent_run.finished
  • agent_task.updated
Sample data
A delivery
POST /hooks/lumtry HTTP/1.1
Content-Type: application/json
User-Agent: Equali-Webhooks/1
X-Equali-Delivery-Id: 01J9Z3N6W2D8H4K0P7S5V1X3C9
X-Equali-Event: refund_case.approved
X-Equali-Sequence: 42
X-Equali-Timestamp: 1790258531
X-Equali-Signature: v1=5f2b9d0e…c81e

{
  "created_at": "2026-09-24T14:02:11Z",
  "data": {
    "amount_minor": 4999,
    "currency": "USD",
    "external_order_id": "10442",
    "previous_state": "PENDING_APPROVAL",
    "refund_case_id": "01J9Z3K4M8Q2V6X0B5N7T1R3Y8",
    "state": "APPROVED"
  },
  "id": "01J9Z3N6W2D8H4K0P7S5V1X3C9",
  "sequence": 42,
  "type": "refund_case.approved"
}
Verify it (Node.js)
import crypto from "node:crypto";

// rawBody: the exact bytes received, before JSON parsing.
export function verifyLumtry(rawBody, headers, secret /* whsec_… */) {
  const ts = headers["x-equali-timestamp"];
  const sig = headers["x-equali-signature"] ?? "";
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
  const expected =
    "v1=" + crypto.createHmac("sha256", secret).update(ts + "." + rawBody).digest("hex");
  const a = Buffer.from(sig);
  const b = Buffer.from(expected);
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Reject a timestamp more than 5 minutes old, then compare the HMAC in constant time.

Inbound webhooks are verified before anything is written

Every provider that sends Lumtry a webhook is checked against its own signature scheme first. An invalid signature gets a 401 and no business processing.

  • Shopify
  • Stripe
  • PayPal
  • WooCommerce
  • BigCommerce
  • Amazon SNS
  • eBay
  • Gorgias
  • Zendesk
  • EasyPost
  • Shippo
  • ShipBob
  • ShipHero
  • Twilio
  • Telnyx
  • Slack

Connect your AI assistant in minutes.

Read tools work with any workspace API key. Start free, create a key, and point your assistant at your workspace.