Adjoin
Sign inMonetize my app
← Documentation

REST API

Everything the dashboard does, over HTTPS with an API key.

Authentication

Create a key in Settings → API keys and send it as a bearer token. Keys are shown once.

curl https://api.adjoin.dev/v1/me \
  -H "Authorization: Bearer adj_live_…"
read
GET requests.
write
Create and change campaigns, sites and placements.
conversions
Only the server-to-server conversion endpoints.

A key is never an admin, and cannot create keys or request payouts — those need a signed-in person.

Money is always an integer in micros: 1 USD = 1,000,000.

Endpoints

GET /v1/me
Who the key belongs to.
GET /v1/campaigns
Your campaigns with status, bid, budget and spend.
POST /v1/campaigns
Create a campaign; starts in review. Budget is held from your prepaid balance.
POST /v1/campaigns/plan
Starting bid, reach forecast and reserve for a budget, before you commit.
GET /v1/refunds?campaign_id=cmp_…
Clicks we filtered and did not bill, with the reason for each.
POST /v1/conversions/s2s
Confirm a conversion from your server.
POST /v1/conversions/s2s/refund
Reverse a confirmed order inside its return window.
GET /v1/sites · POST /v1/sites
Your sites; register a domain.
POST /v1/sites/{site_id}/verify
Check domain ownership (DNS TXT, file or meta tag).
GET /v1/placements?site_id= · POST /v1/placements
Slots on a site; create one.
GET /v1/placements/{placement_id}/live
Whether a slot has received requests in the last 24 hours.
GET /v1/boost · POST /v1/boost
Launch Day Boost status; claim it for a campaign.
GET /v1/credits
Cross-promotion credit balance and recent activity.
GET /v1/segments
Audience labels publishers have set, with 7-day pageviews (only labels with 100+). Use them in target_segments / exclude_segments when creating a campaign.

Create a campaign

pricing_model is one of cpc, cpm, cpa, affiliate, guaranteed or cross_promo (paid in credit, no cash budget). A 402 means your available balance is too low.

curl -X POST https://api.adjoin.dev/v1/campaigns \
  -H "Authorization: Bearer adj_live_…" -H "Content-Type: application/json" \
  -d '{
    "name": "Launch",
    "pricing_model": "cpc",
    "bid_micros": 300000,
    "total_budget_micros": 50000000,
    "daily_cap_micros": 5000000,
    "target_categories": ["devtools"],
    "creatives": [{ "headline": "Ship faster", "body": "…", "cta": "Try it",
                    "landing_url": "https://myapp.dev", "format": "card" }]
  }'

Server-to-server conversions

Set the campaign’s conversion source to s2s, then confirm orders from your server with a key that has the conversions scope. The pixel stops billing for that campaign, so one order is never charged through both paths. Clicks can be confirmed for 7 days.

# the ad click lands on https://myapp.dev/?aj_t=… — keep aj_t with the order
curl -X POST https://api.adjoin.dev/v1/conversions/s2s \
  -H "Authorization: Bearer adj_live_…" -H "Content-Type: application/json" \
  -d '{ "click_token": "<aj_t>", "order_id": "order_1234", "value_micros": 29000000 }'

# a return or cancellation, inside the return window
curl -X POST https://api.adjoin.dev/v1/conversions/s2s/refund \
  -H "Authorization: Bearer adj_live_…" -H "Content-Type: application/json" \
  -d '{ "campaign_id": "cmp_…", "order_id": "order_1234" }'

Errors

Errors are JSON with a detail field. 401: missing or invalid key. 403: the key lacks the scope. 404 is also returned for other accounts’ objects, so their existence is never revealed.

Questions: [email protected]