> AffiliateOS Help Center. Index of every article for AI tools: https://www.affiliateos.ai/help/llms.txt

# Network API and postbacks

Running a network · For networks · Updated 30 October 2026
Web version: https://www.affiliateos.ai/help/networks/network-api-and-postbacks

Your server pulls every offer your network can run from `GET /network-api/offers`, with your network key in the `x-api-key` header. You send each user to the offer's `trackingUrl` with their ID in `sub_id`. When one converts, we send a GET request to your postback URL with that ID and what you earned.

## Steps

### Workspace settings, then API Keys, then Generate Key

The key starts with `ak_` and is shown once. **Expires** shows the date it stops working, 90 days after you generate it by default, so rotate before then. The line above the list, such as "Used 1 / 1 keys", shows your limit. With a free slot, generate the new key, move your server to it, then **Remove** the old one. At the limit, **Remove** the old key first, then generate, and expect a short gap. [Create, rotate and revoke API keys](https://www.affiliateos.ai/help/account/create-rotate-revoke-api-keys) has the details.

### Fetch offers

```bash
curl -G "https://affiliateos.xyz/network-api/offers" \
  -d country=US -d platform=ios \
  -d page=1 -d per_page=50 \
  -H "x-api-key: $NORTHFOLD_NETWORK_KEY"
```

Example for Northfold Media. The offers come back in `data.offers`, and paging details in `data.pagination`. Pages hold 50 offers unless you set `per_page`; keep asking for the next `page` while `has_more_pages` is `true`. `/publisher-api/offers` is the same route under its older name.

### Send users through the tracking link

Each offer's `trackingUrl` already carries the offer in `off_id` and your network in `pub_id`. Leave both as they are. Replace `{SUB_ID}` with your user's ID, a different value for every user, and `{DEVICE_ID}` with the device's advertising ID when you have it: advertisers attribute and approve more conversions with it. Left as it is, `{DEVICE_ID}` is dropped and the click still works.

### Workspace settings, then Postback Configuration

Paste your URL into **Postback URL** and choose **Save Changes**. Use HTTPS: every postback carries your user's ID.

### Generate Webhook Secret

Choose **Generate Webhook Secret** and copy it. It starts with `ps_` and is shown once. From then on every postback carries a `verifier`: the HMAC-SHA256 of the full URL up to `&verifier=`, keyed with your secret. Recompute it on your server and refuse any request that doesn't match.

> **Without a secret, postbacks go unsigned.** They still arrive, but your server has no way to tell ours from a forged one. To change it, choose **Revoke**, then **Generate Webhook Secret**. Postbacks sent between the two carry no `verifier`, so update your server right away.

### Check it worked

Choose **Test Postback**. Your server gets a request with `test=true` added: log it and don't credit anyone. A passing test proves your URL is reachable, not that live conversions are flowing. After the first real conversion, **Reporting**, then **Flight Recorder** shows its timeline through to your postback.

## What each postback carries

| Parameter | When | Meaning |
|---|---|---|
| `action_id` | Always | Unique ID of this conversion |
| `sub_id` | Always | The user ID you put on the tracking link |
| `offer_id` | Always | The offer that converted |
| `status` | Always | `completed` or `reversed` |
| `payout` | Always | What your network earns for this conversion, in USD |
| `conversion_name` | Always | The step's name, or the offer's name when it has no separate steps |
| `clicktimestamp` | Always | When the click happened. The format varies and it can be empty, so parse it loosely. |
| `is_offer_complete` | Always | `true` when no steps are left |
| `goal_id` | Offers with several steps | Which step this was |
| `offer_name` | When the offer resolves | The offer's title. Store it: an ended offer can't be looked up later. |
| `user_payout` | When the offer sets a player reward | The player's reward for this step, in USD |
| `verifier` | With a webhook secret | The signature above |
| `test` | Tests only | `true` |

Offers with several steps send one postback per step, each with its own `action_id` and `payout`.

> **Install-paid games pay your network once, at install.** Their later steps still post back, with `payout=0` and, when the offer sets one, the player's reward in `user_payout`, so you can keep crediting the player.

## Answer every postback

- Reply with HTTP 200.
- Keep each `action_id` with its `status`. A repeat of a postback you already handled changes nothing; `status=reversed` means take back what you credited for it.
- Credit `user_payout` to the player when it's present.

The full reference, with Node and curl samples, is in the [Network API docs](https://www.affiliateos.ai/help/developers#network-api).
