> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tracklysms.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Offer

> Create a new offer with a tracking URL and optional platform integration.

Creates a new offer on your account. At minimum, a `name` and `tracking_url` are required. You can optionally link the offer to an external affiliate platform such as TUNE or Everflow.

## Body Parameters

<ParamField body="name" type="string" required>
  Display name for the offer. Maximum 255 characters.
</ParamField>

<ParamField body="tracking_url" type="string" required>
  The tracking/click URL for this offer. Must be a valid URL.
</ParamField>

<ParamField body="external_platform" type="string" optional>
  External affiliate platform integration. Accepted values: `tune`, `everflow`, or `null`.
</ParamField>

<ParamField body="external_id" type="string" optional>
  The offer ID on the external platform. Useful for syncing data with TUNE or Everflow.
</ParamField>

<ParamField body="advertiser_id" type="string" optional>
  Advertiser ID associated with the offer.
</ParamField>

<ParamField body="payout" type="float" optional default="0">
  Payout amount for the offer.
</ParamField>

<ParamField body="payout_type" type="string" optional default="cpa">
  Payout model. Accepted values: `cpa` (cost per action) or `cpc` (cost per click).
</ParamField>

<ParamField body="filter_bots" type="boolean" optional default="false">
  Whether to enable bot click filtering for this offer. When enabled, suspected bot clicks are flagged and excluded from reporting.
</ParamField>

<ParamField body="status" type="string" optional default="active">
  Initial status of the offer. Accepted values: `active` or `paused`.
</ParamField>

<ParamField body="metadata" type="object" optional>
  Custom key-value pairs for storing additional information about the offer. Stored as-is; no type validation is enforced on keys or values, so nested objects, numbers, and booleans are accepted.
</ParamField>

<ParamField body="excluded_days_of_week" type="array" optional>
  Weekday names (lowercase `monday` through `sunday`) on which the SMS ad server will not send this offer, evaluated in the contact's local time. Duplicates are removed and the list is normalized to weekday order.
</ParamField>

<ParamField body="day_parting_enabled" type="boolean" optional default="false">
  Whether intra-day send-window restrictions apply. When `true`, `day_parting` must be non-empty or the request is rejected with `invalid_day_parting`.
</ParamField>

<ParamField body="day_parting" type="object" optional>
  Allow-list of send windows keyed by lowercase weekday, evaluated in Eastern Time. Shape: `{"monday": [{"start": "HH:MM", "end": "HH:MM"}]}`. Times are 24-hour zero-padded; `start` must be before `end` (no overnight crossing); maximum 6 ranges per day. Omit a weekday to block sending on that day.
</ParamField>

## Response Fields

<ResponseField name="success" type="boolean">
  Indicates whether the offer was created successfully.
</ResponseField>

<ResponseField name="offer" type="object">
  The full offer object. See [List Offers](/api-reference/v2/offers/list-offers) for the complete field reference.
</ResponseField>

## Examples

<RequestExample>
  <CodeGroup>
    ```bash cURL theme={null}
    curl -X POST "https://api.tracklysms.com/api/v2/offers" \
      -H "X-Api-Key: trk_your_api_key_here" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "Summer Promo",
        "tracking_url": "https://track.example.com/click?offer_id=123",
        "external_platform": "tune",
        "external_id": "4521",
        "advertiser_id": "adv_882",
        "payout": 2.50,
        "payout_type": "cpa",
        "filter_bots": true,
        "metadata": {
          "vertical": "health",
          "geo": "US"
        }
      }'
    ```

    ```python Python theme={null}
    import requests

    response = requests.post(
        "https://api.tracklysms.com/api/v2/offers",
        headers={
            "X-Api-Key": "trk_your_api_key_here",
            "Content-Type": "application/json"
        },
        json={
            "name": "Summer Promo",
            "tracking_url": "https://track.example.com/click?offer_id=123",
            "external_platform": "tune",
            "external_id": "4521",
            "advertiser_id": "adv_882",
            "payout": 2.50,
            "payout_type": "cpa",
            "filter_bots": True,
            "metadata": {
                "vertical": "health",
                "geo": "US"
            }
        }
    )

    data = response.json()
    print(data["offer"]["id"])
    ```

    ```javascript Node.js theme={null}
    const response = await fetch("https://api.tracklysms.com/api/v2/offers", {
      method: "POST",
      headers: {
        "X-Api-Key": "trk_your_api_key_here",
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        name: "Summer Promo",
        tracking_url: "https://track.example.com/click?offer_id=123",
        external_platform: "tune",
        external_id: "4521",
        advertiser_id: "adv_882",
        payout: 2.50,
        payout_type: "cpa",
        filter_bots: true,
        metadata: {
          vertical: "health",
          geo: "US"
        }
      })
    });

    const data = await response.json();
    console.log(data.offer.id);
    ```
  </CodeGroup>
</RequestExample>

<ResponseExample>
  ```json 201 - Created theme={null}
  {
    "success": true,
    "offer": {
      "id": "664f1a2b3c4d5e6f7a8b9c0d",
      "slug": "ofr_summer-promo_a1b2c3",
      "name": "Summer Promo",
      "tracking_url": "https://track.example.com/click?offer_id=123",
      "external_platform": "tune",
      "external_id": "4521",
      "advertiser_id": "adv_882",
      "advertiser_name": null,
      "payout": 2.50,
      "payout_type": "cpa",
      "filter_bots": true,
      "status": "active",
      "metadata": {
        "vertical": "health",
        "geo": "US"
      },
      "excluded_days_of_week": [],
      "day_parting_enabled": false,
      "day_parting": {},
      "created_at": "2025-11-01T14:30:00",
      "updated_at": "2025-11-01T14:30:00"
    }
  }
  ```

  ```json 400 - Validation Error theme={null}
  {
    "error": "name is required",
    "code": "missing_name"
  }
  ```

  ```json 401 - Unauthorized theme={null}
  {
    "error": "Invalid credentials",
    "code": "invalid_credentials"
  }
  ```
</ResponseExample>

## Error Codes

| HTTP Status | Error Code                  | Description                                                                                 |
| ----------- | --------------------------- | ------------------------------------------------------------------------------------------- |
| 400         | `missing_name`              | The `name` field was not provided.                                                          |
| 400         | `missing_tracking_url`      | The `tracking_url` field was not provided.                                                  |
| 400         | `name_too_long`             | The `name` exceeds 255 characters.                                                          |
| 400         | `invalid_external_platform` | The `external_platform` value is not `tune`, `everflow`, or `null`.                         |
| 400         | `invalid_payout_type`       | The `payout_type` value is not `cpa` or `cpc`.                                              |
| 400         | `invalid_status`            | The `status` value is not `active` or `paused`.                                             |
| 400         | `invalid_excluded_days`     | `excluded_days_of_week` is not a list or contains a non-weekday value.                      |
| 400         | `invalid_day_parting`       | `day_parting` is malformed, or `day_parting_enabled` is `true` with an empty `day_parting`. |
| 401         | `invalid_credentials`       | API key is missing or invalid.                                                              |
| 403         | `account_suspended`         | Your account is suspended. Resolve outstanding billing or contact support.                  |
| 429         | `rate_limited`              | Request throttled; retry with exponential backoff after the window resets.                  |
| 500         | `server_error`              | An unexpected error occurred on the server.                                                 |

## Next Steps

<CardGroup cols={2}>
  <Card title="Offers Overview" icon="tag" href="/guides/offers/overview">
    Learn about offer management
  </Card>

  <Card title="Record Revenue" icon="dollar-sign" href="/api-reference/v2/revenue/record-revenue">
    Track revenue for your offers
  </Card>
</CardGroup>
