The API is the product — everything the dashboard does goes through the same endpoints. Authenticate with the API key issued for your org (dashboard → Settings, or ask your Hotswap contact) as a bearer token:
curl https://api.1tap.at/v1/org \
-H "Authorization: Bearer 1tap_live_xxxxxxxxxxxxxxxxxxxxxxxx"
| Endpoint | What it does |
|---|---|
GET /v1/org | Your org, plan and usage. |
POST /v1/links | Create a link: {"domain","destination_url","short_code?","title?","expires_at?","rules?"}. Alias auto-generates when omitted. rules = smart routing (below). |
GET /v1/links | List links (keyset pagination via ?limit=&cursor=). |
PATCH /v1/links/{id} | Change destination, title, status (active|paused), expiry or rules ("rules": null clears). |
DELETE /v1/links/{id} | Delete (org-admin / API key only). |
POST /v1/links/bulk?domain= | CSV body (destination_url,short_code,title header, ≤1000 rows) → per-row results. |
GET /v1/links/report?range=30d | Every link with clicks (range) + conversions (all-time) — the "did my batch get clicked" call. |
GET /v1/analytics?type=&range=&link_id= | overview · timeseries · top_links · countries · devices · referrers. |
POST/GET /v1/domains, POST /v1/domains/{id}/verify | Connect and verify custom domains. |
PUT /v1/integrations | Configure Meta CAPI: {"provider":"meta_capi","config":{"pixel_id","access_token"}}. |
POST /v1/conversions | Public — see the snippet below; requires a valid click_id. |
POST/GET /v1/folders | Projects to organize links. Set folder_id + tags on a link; filter with ?folder_id= / ?tag=. |
POST/GET/DELETE /v1/webhooks | Subscribe an endpoint to conversion.created, link.clicked, campaign.clicked. See below. |
POST/GET /v1/campaigns | Stateless bulk — see below. |
For one-per-customer sends (email/WhatsApp) where you only need "who clicked". Create one campaign; links are computed and signed, never stored; a row is written only when a customer actually clicks theirs.
POST /v1/campaigns
{ "domain": "go.yourbrand.com", "name": "Diwali WA",
"destination_template": "https://yourbrand.com/welcome?c={ref}", "sent_count": 1000000 }
→ { "campaign": { "id": "camp_…", "secret": "…", "link_pattern": "https://go.yourbrand.com/c/camp_….{base64url(ref)}.{hmac16}", … } }
Get each customer's link — batched (≤10k/call), no writes:
POST /v1/campaigns/camp_…/generate { "refs": ["cust-1","cust-2", …] }
→ { "links": [ { "ref": "cust-1", "url": "https://go.yourbrand.com/c/camp_….Y3VzdC0x.a1b2c3d4e5f6a7b8" }, … ] }
Or generate all 1M locally with zero API calls — for each ref:
sig = HMAC_SHA256(campaign.secret, campaignId + "." + ref) // first 16 hex chars
link = https://{domain}/c/{campaignId}.{base64url(ref)}.{sig}
Then pull the clickers:
GET /v1/campaigns/camp_…/clicks?limit=1000&cursor=…
→ { "clicks": [ { "ref": "cust-1", "click_count": 2, "first_clicked_at": …, "last_clicked_at": … } ], "cursor": … }
Register an endpoint and pick events. Every delivery is POST {event, created_at, data}
with an X-1Tap-Signature header = HMAC-SHA256 of the raw body using the secret
returned on create. Best-effort (no retries) — verify the signature, respond 2xx.
POST /v1/webhooks { "url": "https://yourapp.com/hooks/1tap", "events": ["conversion.created"] }
→ { "id": "wh_…", "secret": "whsec_…" } // secret shown once
Errors are always {"error":{"message":"…"}} with a meaningful status (400
validation, 401/403 auth, 404 not-yours-or-missing, 409 conflict, 429 slow-down).
Rules evaluate top-down, first match wins, all conditions in a rule must match; no match → the default destination:
{
"domain": "go.yourbrand.com",
"destination_url": "https://yourbrand.com/sale",
"rules": {
"version": 1,
"rules": [
{ "country": ["IN"], "device": "mobile", "to": "https://yourbrand.onelink.me/app" },
{ "percent": 50, "to": "https://yourbrand.com/sale-b" },
{ "schedule": { "end": 1767206400 }, "to": "https://yourbrand.com/pre-launch" }
]
}
}
1) Ask us (or your org admin) to turn attribution on — your links start appending a
signed ?1tap_id=. 2) Add the snippet to the destination site:
<script src="https://1tap.at/1tap-convert.js" async></script>
3) Call it when the visitor converts — same visit or up to 30 days later:
_1tap.convert(); // a lead
_1tap.convert("Purchase", 1499, "INR"); // a purchase with value
Conversions appear in your link report. If Meta CAPI is configured, each event is also
forwarded server-side to Meta with event_id deduplication — safe to run
alongside a browser pixel.
Prefer raw HTTP? POST /v1/conversions with
{"click_id","event_name?","value?","currency?"} — no auth header; the signed
click id is the credential.