Docs · v1.0

Reference for operators and the engineers who support them.

Everything from audit scoping to raw API keys. Written by the team that ships the code, no ghostwriters, no stale screenshots.

01 · Quickstart

Get a tenant live in an afternoon.

From a kickoff call to a working attribution pipeline takes about six hours of engineering time on our side and a handful of credentials from yours. The path below assumes you're running a multi-location restaurant app with POS and a loyalty program already in place.

1. Claim your workspace

After the audit kickoff, a workspace is provisioned at https://app.dualasolutions.com/{tenant}. Your first admin gets a magic link via the email on file.

2. Connect a POS

We maintain first-party connectors for the four POS systems that cover roughly 90% of the Canadian multi-location market. See integrations for the list and auth flow.

3. Verify ingest

Drop the curl below to check that the first day of events landed correctly. You should see a count within ~0.5% of what your POS reports.

# Verify the ingest pipeline picked up yesterday's transactions
curl https://api.dualasolutions.com/v1/ingest/verify \
  -H "Authorization: Bearer $DUALA_TOKEN" \
  -d '{ "range": "yesterday", "brand_id": "ch-on-001" }'
02 · Data Readiness Audit

Eighty signals, four buckets, one roadmap.

The audit inventories 80+ signals across POS, loyalty, CDP, and paid media. Each signal is rated on two dimensions: completeness (do you have it?) and resolvability (can we tie it to a specific customer?). You'll walk away with a scored report and a sequence of fixes ordered by dollar impact.

  • POS layer, order IDs, modifier-level breakdowns, refunds, staff attribution, table/mobile/drive-thru flags.
  • Loyalty layer, member resolution, reward redemption events, tier changes, referral tree.
  • CDP / CRM layer, campaign IDs, offer codes, segment membership at time-of-send.
  • Paid media layer, channel + creative IDs, last-touch and position-based windows, store-visit conversions.
03 · Attribution Signals

The resolver explained.

Every order that enters the pipeline is run through a resolver that layers deterministic matches (loyalty ID, auth'd phone, offer code) before falling back to probabilistic ones (device, location, cohort). The output is a customer_resolution event with a confidence score.

{
  "order_id": "ch-on-003-2026-04-16-88291",
  "resolved_to": "cust_0F8N3…",
  "method": "loyalty_id",
  "confidence": 0.99,
  "attributions": [
    { "campaign": "spring-boba-2026", "channel": "sms", "weight": 0.70 },
    { "campaign": "app-push-april", "channel": "push", "weight": 0.30 }
  ]
}
04 · Integrations

First-party connectors.

Connectors below are maintained by the core team. Anything not on this list can be hit via the generic webhook-to-warehouse path, we'll build you a proper connector if you're on Priority or Enterprise.

  • POS, Square for Restaurants, Toast, Revel, TouchBistro.
  • Loyalty, Paytronix, Punchh, Como, Thanx, in-house via SDK.
  • CDP / CRM, Segment, mParticle, Braze, Klaviyo, HubSpot.
  • Paid media, Meta, Google Ads, TikTok Ads, Snap Ads.
  • Automation, Zapier, Make, native webhooks.
05 · API Reference

REST endpoints for operators.

All requests are made against https://api.dualasolutions.com/v1. Auth is Bearer token scoped to a single brand.

GET/brands/{id}Fetch brand metadata and connected integrations.
GET/attribution/campaigns/{id}Return rolled-up attribution for a campaign with channel breakdown.
POST/events/orderStream an order event into the resolver. Idempotent on order_id.
POST/events/redemptionRecord a loyalty reward redemption against a customer + campaign.
GET/cohorts/{id}/liftPre-post cohort lift with the measurement window you passed in.
DEL/customers/{id}GDPR / PIPEDA right-to-erasure. Async, returns a deletion receipt.
06 · Webhooks

Push events into your stack.

Register a webhook for any event in the resolver pipeline. Payloads are signed with HMAC-SHA256 using your webhook secret.

POST /your-endpoint
Content-Type: application/json
X-Duala-Signature: sha256=8b3a1f…
X-Duala-Timestamp: 1745928000

{
  "event": "attribution.resolved",
  "occurred_at": "2026-04-16T14:22:13Z",
  "brand_id": "ch-on-001",
  "data": { ... }
}