REST

Campaigns

List existing campaigns or create a new one. Campaigns auto-generate UTM tracking links for each selected channel. Results are cursor-paginated.

GET/api/v1/sites/:siteId/campaigns

List campaigns

Returns all campaigns for a site with click and session totals, channel breakdown, and a 30-day click sparkline. Results are cursor-paginated.

Paginated — supports cursor and limit

Request

bash
curl -X GET \
  'https://letoseo.com/api/v1/sites/:siteId/campaigns' \
  -H 'Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

Path parameters

NameTypeRequiredDescriptionDefault
siteIduuidrequiredThe site UUID.

Query parameters

NameTypeRequiredDescriptionDefault
status"draft" | "active" | "paused" | "completed"optionalFilter campaigns by lifecycle status.
cursorstringoptionalOpaque pagination cursor from a previous response.
limitintegeroptionalNumber of items per page. Min 1, max 100.25

Responses

200Paginated list of campaigns.
json
{
  "data": {
    "items": [
      {
        "id": "00000000-0000-0000-0000-000000000010",
        "name": "Acme Q1 Launch",
        "slug": "acme-q1-launch",
        "status": "active",
        "description": "Q1 product launch campaign.",
        "destination_url": "https://acme-demo.example/launch",
        "starts_at": "2025-01-06T00:00:00.000Z",
        "ends_at": "2025-03-31T23:59:59.000Z",
        "created_at": "2025-01-05T12:00:00.000Z",
        "total_clicks": 342,
        "total_sessions": 187,
        "channels": [
          "organic",
          "email",
          "social"
        ],
        "sparkline": [
          {
            "date": "2025-01-14",
            "value": 28
          },
          {
            "date": "2025-01-15",
            "value": 34
          }
        ]
      }
    ],
    "total_count": 1
  },
  "_meta": {
    "generated_at": "2025-01-15T10:30:00.000Z",
    "site_id": "00000000-0000-0000-0000-000000000001"
  }
}
404Site not found.
json
{
  "error": "Site not found"
}
POST/api/v1/sites/:siteId/campaigns

Create a campaign

Creates a new campaign and auto-generates UTM tracking links for each selected channel. destination_url must be HTTPS and must not already contain UTM parameters. Returns the created campaign row at 201.

Request

bash
curl -X POST \
  'https://letoseo.com/api/v1/sites/:siteId/campaigns' \
  -H 'Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Acme Q1 Launch",
    "destination_url": "https://acme-demo.example/launch",
    "description": "Q1 product launch campaign.",
    "starts_at": "2025-01-06T00:00:00.000Z",
    "ends_at": "2025-03-31T23:59:59.000Z",
    "channels": [
      "organic",
      "email",
      "social"
    ]
  }'

Path parameters

NameTypeRequiredDescriptionDefault
siteIduuidrequiredThe site UUID.

Request body (application/json)

NameTypeRequiredDescriptionDefault
namestringrequiredHuman-readable campaign name.
destination_urlstring (URL)requiredHTTPS destination URL. Must not contain existing UTM parameters.
descriptionstringoptionalOptional longer description.
starts_atstring (ISO 8601)optionalCampaign start date. If provided, status is set to "active".
ends_atstring (ISO 8601)optionalCampaign end date.
channelsstring[]optionalChannel keys to generate UTM links for. Defaults to the system default channel set.

Example

json
{
  "name": "Acme Q1 Launch",
  "destination_url": "https://acme-demo.example/launch",
  "description": "Q1 product launch campaign.",
  "starts_at": "2025-01-06T00:00:00.000Z",
  "ends_at": "2025-03-31T23:59:59.000Z",
  "channels": [
    "organic",
    "email",
    "social"
  ]
}

Responses

201Campaign created. Body contains the new campaign row.
json
{
  "data": {
    "id": "00000000-0000-0000-0000-000000000010",
    "site_id": "00000000-0000-0000-0000-000000000001",
    "user_id": "00000000-0000-0000-0000-000000000099",
    "name": "Acme Q1 Launch",
    "slug": "acme-q1-launch",
    "utm_id": "acme01",
    "description": "Q1 product launch campaign.",
    "destination_url": "https://acme-demo.example/launch",
    "status": "active",
    "starts_at": "2025-01-06T00:00:00.000Z",
    "ends_at": "2025-03-31T23:59:59.000Z",
    "created_at": "2025-01-15T10:30:00.000Z",
    "updated_at": "2025-01-15T10:30:00.000Z"
  },
  "_meta": {
    "generated_at": "2025-01-15T10:30:00.000Z",
    "site_id": "00000000-0000-0000-0000-000000000001"
  }
}
400name or destination_url missing, or destination_url contains UTM params or is not HTTPS.
json
{
  "error": "name and destination_url are required"
}
404Site not found.
json
{
  "error": "Site not found"
}