Skip to content
Docs

Getting started

First offer in 10 minutes

Create an advertiser, a partner and an offer, get a tracking link, click it and record a test conversion.

This walkthrough uses the API so every step is copy-pasteable; each step is also available in the admin portal (Network, Offers). You need an API key with write access (see authentication) and one verified tracking domain. Replace the base URL if you self-host.

bash
export API=https://api.metrixed.com/v1
export DT_API_KEY=...   # admin portal: Settings, API keys
auth=(-H "Authorization: Bearer $DT_API_KEY" -H "Content-Type: application/json")

1. Create the advertiser

The advertiser's security mode decides how its postbacks are authenticated. token is the simplest: the advertiser sends security_token=... with every postback.

bash
curl -s "${auth[@]}" -X POST $API/advertisers \
  -d '{"name":"Acme Shop","status":"active","postback_security_mode":"token"}'

Keep the returned id as ADV. A random security_token is generated for the advertiser (read it from the response or GET /advertisers/ADV); give it to the advertiser, who must send it with every postback.

2. Create the partner

bash
curl -s "${auth[@]}" -X POST $API/partners -d '{"name":"Jane Media","status":"active"}'

Keep the id as PARTNER.

3. Create the offer

Only name, advertiser_id and destination_url are required. Macros in the destination are filled in at click time; {click_id} is what the advertiser must send back.

bash
curl -s "${auth[@]}" -X POST $API/offers -d '{
  "name": "Acme spring sale",
  "advertiser_id": "ADV",
  "status": "active",
  "visibility": "public",
  "currency": "USD",
  "destination_url": "https://acme.example/landing?cid={click_id}&src={source}",
  "conversion_method": "server_postback",
  "session_duration_hours": 720
}'

session_duration_hours is the click-to-conversion attribution window (720 hours is 30 days). Other defaults worth knowing: redirect mode http302, attribution last_touch, no cookies.

4. Add a goal and a payout

A goal is the result you pay for. Its key is what postbacks send in goal.

bash
curl -s "${auth[@]}" -X POST $API/offers/OFFER/goals -d '{"name":"Sale","key":"sale","event_category":"sale","revenue_semantics":"from_sale_amount"}'

curl -s "${auth[@]}" -X POST $API/offers/OFFER/payouts -d '{
  "goal_id": "GOAL", "payout_type": "percent_of_sale", "payout_percentage": "10",
  "revenue_type": "percent_of_sale", "revenue_percentage": "14",
  "currency": "USD", "is_default": true, "status": "active"
}'

Payout types are fixed, percent_of_sale, fixed_plus_percent, per_click, per_mille, per_sku, kpi_scaled, tiered and blank. Money is always a decimal string. See billing and payouts for overrides, tiers and scrub.

Public offers are open to every active partner. For require_approval offers grant access first with PUT /partners/{id}/offers/{offerId} (see partners) or approve the partner's application.

A native tracking link is https://<tracking-domain>/c/<offer hash>/<partner hash>, where the hashes are the hash_id fields of the offer and the partner:

bash
curl -s "${auth[@]}" $API/offers/OFFER | jq -r .hash_id      # OFFER_HASH
curl -s "${auth[@]}" $API/partners/PARTNER | jq -r .hash_id  # PARTNER_HASH
curl -s "${auth[@]}" "$API/tracking-domains?filter[status]=active" | jq -r '.data[].host'

Or let the API build it. POST /offers/{id}/tracking-link returns the native link on the default tracking domain plus every other link style, the impression URL and, on request, pixels and a QR code:

bash
curl -s "${auth[@]}" -X POST $API/offers/OFFER/tracking-link \
  -d '{"partner_id":"PARTNER","params":{"sub1":"newsletter-42"}}' | jq -r .url

The admin portal's Traffic, Link builder does the same with sub1 to sub10, QR codes and pixels.

6. Click it

bash
curl -si "https://go.yourbrand.com/c/OFFER_HASH/PARTNER_HASH?sub1=newsletter-42&test=1"

You get a 302 to the destination with {click_id} replaced, and an X-Click-Id response header. test=1 marks the click as test traffic: it is stored and shows in the logs with is_test set, but is excluded from reports and never reaches the ledger.

7. Report a conversion

This is what the advertiser's server does after the sale. Replace the click id:

bash
curl -s "https://go.yourbrand.com/p?click_id=CLICK_ID&goal=sale&txn_id=ORDER-1001&amount=49.90&currency=USD&security_token=TOKEN&test=1"
json
{"status":"created","conversion_id":"01J...","conversion_status":"approved"}

Send the same request again and the answer is {"status":"duplicate", ...}: conversions de-duplicate on txn_id per offer and goal. See conversion tracking methods.

8. Look at it

In the admin portal open Insights, Logs and the Conversions tab: the row shows the matched click, the payout entry that priced it (here 10% of 49.90 = 4.99) and every decision taken. Insights, Investigator finds the click or conversion from any id, IP or email, and the testers replay and explain traffic without writing data.

Troubleshooting

SymptomLikely cause
Click returns 204 or your fallback URLOffer paused or expired, partner inactive or blocked, or a rule denied it. The click log has the invalid_reason.
Postback answers rejected with invalid_tokensecurity_token missing or wrong for an advertiser in token mode.
unmatchedThe click_id is unknown (typo, other tenant) or its click was never recorded. Without a click id and no other match the conversion is stored but unattributed.
rejected with expired_sessionConversion arrived after session_duration_hours.