> ## 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.

# V1 to V2 Migration Guide

> Everything you need to know to migrate your integration from the Trackly SMS v1 API to v2

# V1 to V2 Migration Guide

The v2 API is a complete evolution of the Trackly SMS platform API. It introduces new resources, cleaner naming conventions, and fully functional CRUD endpoints. This guide covers every breaking change and new feature to help you migrate smoothly.

<Warning>
  The v1 API is **deprecated**. All v1 responses now include deprecation headers. While v1 endpoints continue to function, we strongly recommend migrating to v2 as soon as possible.
</Warning>

***

## What's Still the Same

Before diving into changes, here is what has **not** changed:

* **Base URL**: `https://api.tracklysms.com/api`
* **Authentication**: The `X-Api-Key` header with your `trk_[32-char-alphanumeric]` key works identically in v2.
* **Content type**: All requests use `Content-Type: application/json`.
* **HTTP methods**: Standard REST conventions (GET, POST, PUT, PATCH, DELETE).

***

## V1 Deprecation Headers

All v1 responses now include deprecation headers to signal that the endpoint is deprecated:

```http theme={null}
HTTP/1.1 200 OK
X-API-Deprecated: v1 is deprecated
Deprecation: true
Content-Type: application/json
```

| Header             | Value              | Description                                          |
| ------------------ | ------------------ | ---------------------------------------------------- |
| `X-API-Deprecated` | `v1 is deprecated` | Custom header indicating the endpoint is deprecated. |
| `Deprecation`      | `true`             | Standard deprecation header per RFC 8594.            |

***

## Key Field Renames

The most impactful change is the renaming of core fields used in message sending.

| Concept          | v1 Field Name          | v2 Field Name | Format |
| ---------------- | ---------------------- | ------------- | ------ |
| Sending number   | `from_phone_number_id` | `list_number` | E.164  |
| Recipient number | `to_msisdn` or `to`    | `to`          | E.164  |

### Important Notes

* **`list_number`** replaces `from_phone_number_id`. In v1, you passed a Trackly ID for the sending number. In v2, you pass the phone number itself in E.164 format (e.g. `+14155551234`).
* **`to`** remains the same field name but now strictly requires E.164 format (e.g. `+14155556789`).

***

## Response Format Changes

All v2 responses include a top-level `success` boolean field:

**V2 success response:**

```json theme={null}
{
  "success": true,
  "message_id": "AbC12345",
  "status": "queued"
}
```

**V2 error response:**

```json theme={null}
{
  "error": "body is required",
  "code": "missing_body"
}
```

Success responses include a top-level `success: true` field. Error responses return a flat object with `error` (human-readable message) and `code` (machine-readable code) — no `success` field is included in errors.

***

## Endpoint Path Changes

### Message Sending

| Action         | v1 Endpoint              | v2 Endpoint          |
| -------------- | ------------------------ | -------------------- |
| Send a message | `POST /v1/messages`      | `POST /v2/send`      |
| Bulk send      | `POST /v1/messages/bulk` | `POST /v2/send/bulk` |

### Contacts

| Action         | v1 Endpoint            | v2 Endpoint               |
| -------------- | ---------------------- | ------------------------- |
| List contacts  | `GET /v1/contacts`     | `GET /v2/contacts`        |
| Create contact | `POST /v1/contacts`    | `POST /v2/contacts`       |
| Get contact    | `GET /v1/contacts/:id` | `GET /v2/contacts/:id`    |
| Update contact | --                     | `PATCH /v2/contacts/:id`  |
| Delete contact | --                     | `DELETE /v2/contacts/:id` |
| Bulk create    | --                     | `POST /v2/contacts/bulk`  |

<Warning>
  V1 contact endpoints (`/v1/contacts`) are **no-ops** -- they accept requests but do not actually create, update, or persist contacts. V2 contact endpoints are fully functional with real CRUD operations.
</Warning>

***

## New Resources in V2

The following resources are **only available in v2** and have no v1 equivalent:

| Resource           | Endpoints            | Description                                                       |
| ------------------ | -------------------- | ----------------------------------------------------------------- |
| **Lists**          | `/v2/lists`          | Manage sending lists and phone numbers.                           |
| **Creatives**      | `/v2/creatives`      | Create and manage message creatives with offer link placeholders. |
| **Audiences**      | `/v2/audiences`      | Build audience segments with conditions and filters.              |
| **Offers**         | `/v2/offers`         | Manage affiliate offers linked to creatives.                      |
| **Schedules**      | `/v2/schedules`      | Schedule message sends for future delivery.                       |
| **Revenue**        | `/v2/revenue`        | Query revenue and conversion data.                                |
| **History Import** | `/v2/history/import` | Bulk import historical send data.                                 |

***

## Side-by-Side: Sending a Message

### V1 (Deprecated)

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.tracklysms.com/api/v1/messages \
    -H "X-Api-Key: trk_your_api_key_here" \
    -H "Content-Type: application/json" \
    -d '{
      "from_phone_number_id": "6507f1f55bcf86cd799439011",
      "to_msisdn": "+14155556789",
      "body": "Hello from v1!"
    }'
  ```

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

  response = requests.post(
      "https://api.tracklysms.com/api/v1/messages",
      headers={"X-Api-Key": "trk_your_api_key_here"},
      json={
          "from_phone_number_id": "6507f1f55bcf86cd799439011",
          "to_msisdn": "+14155556789",
          "body": "Hello from v1!"
      }
  )

  data = response.json()
  print(data)
  ```

  ```javascript Node.js theme={null}
  const response = await fetch("https://api.tracklysms.com/api/v1/messages", {
    method: "POST",
    headers: {
      "X-Api-Key": "trk_your_api_key_here",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      from_phone_number_id: "6507f1f55bcf86cd799439011",
      to_msisdn: "+14155556789",
      body: "Hello from v1!",
    }),
  });

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

**V1 Response:**

```json theme={null}
{
  "id": "6507f1f55bcf86cd799439011",
  "message_id": "6507f1f55bcf86cd799439011",
  "status": "queued",
  "segments": 1,
  "gsm7": true,
  "deprecated": true
}
```

### V2 (Current)

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.tracklysms.com/api/v2/send \
    -H "X-Api-Key: trk_your_api_key_here" \
    -H "Content-Type: application/json" \
    -d '{
      "list_number": "+14155551234",
      "to": "+14155556789",
      "body": "Hello from v2!"
    }'
  ```

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

  response = requests.post(
      "https://api.tracklysms.com/api/v2/send",
      headers={"X-Api-Key": "trk_your_api_key_here"},
      json={
          "list_number": "+14155551234",
          "to": "+14155556789",
          "body": "Hello from v2!"
      }
  )

  result = response.json()
  if result.get("success"):
      print(f"Queued: {result['message_id']}")
  else:
      print(f"Error: {result.get('error')}")
  ```

  ```javascript Node.js theme={null}
  const response = await fetch("https://api.tracklysms.com/api/v2/send", {
    method: "POST",
    headers: {
      "X-Api-Key": "trk_your_api_key_here",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      list_number: "+14155551234",
      to: "+14155556789",
      body: "Hello from v2!",
    }),
  });

  const result = await response.json();
  if (result.success) {
    console.log(`Queued: ${result.message_id}`);
  } else {
    console.error(`Error: ${result.error}`);
  }
  ```
</CodeGroup>

**V2 Response:**

```json theme={null}
{
  "success": true,
  "message_id": "AbC12345",
  "status": "queued"
}
```

***

## Migration Checklist

Use this checklist to track your migration progress:

* [ ] **Update send endpoint**: Change `POST /v1/messages` to `POST /v2/send`
* [ ] **Rename `from_phone_number_id`**: Replace with `list_number` using the E.164 phone number
* [ ] **Rename `to_msisdn`**: Replace with `to` (if you were using `to_msisdn`)
* [ ] **Handle `success` field**: Update response parsing to check the `success` boolean
* [ ] **Replace contact no-ops**: If you were using `/v1/contacts`, switch to `/v2/contacts` for real CRUD
* [ ] **Adopt new resources**: Evaluate whether `/v2/creatives`, `/v2/audiences`, `/v2/schedules`, and other new endpoints can simplify your integration
* [ ] **Test in development**: Verify all updated endpoints before deploying to production
* [ ] **Remove deprecation header handling**: Once fully migrated, you can stop monitoring for `X-API-Deprecated` headers

***

## Need Help?

If you encounter issues during migration, reach out to our support team. When reporting an issue, include:

1. The full request URL and method
2. The request headers (redact your API key)
3. The request body
4. The full response body and status code

## Next Steps

<CardGroup cols={2}>
  <Card title="V2 API Overview" icon="book" href="/api-reference/v2/overview">
    Explore all v2 endpoints and features
  </Card>

  <Card title="Error Codes" icon="triangle-exclamation" href="/api-reference/v2/error-codes">
    Handle v2 error responses
  </Card>
</CardGroup>
