Skip to content

Campaigns

APIs for managing email campaigns (drafts) in your Lindris account.

As a reminder, all requests must be authenticated and use the base URL: https://api.lindris.com

List campaigns

GET api/campaigns

Retrieve a paginated list of campaigns. Defaults to draft campaigns when no status filter is provided.

Query Parameters

  • status string optional - A single campaign status to filter by, or all for every status. Defaults to draft when omitted. Filtering by sending includes campaigns in the preparing sub-state. Example: sent
    • Must be one of:
      • draft
      • sent
      • scheduled
      • sending
      • paused
      • failed
      • all
  • page integer optional - Page number for pagination. Defaults to 1. Example: 2
  • perPage integer optional - Number of items per page. Defaults to 10, maximum 100. Example: 25
  • sort string optional - Field to sort by. Defaults to the backend's per-status order. Example: createdAt
    • Must be one of:
      • name
      • status
      • createdAt
  • order string optional - Sort direction (requires sort). Defaults to desc. Example: desc
    • Must be one of:
      • asc
      • desc

Request

bash
curl --request GET \
    --get "https://api.lindris.com/api/campaigns?status=sent&page=2&perPage=25&sort=createdAt&order=desc" \
    --header "Authorization: Bearer {YOUR_API_KEY}" \
    --header "Content-Type: application/json"
php
$client = new \GuzzleHttp\Client();
$url = 'https://api.lindris.com/api/campaigns';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_KEY}',
            'Content-Type' => 'application/json',
        ],
        'query' => [
            'status' => 'sent',
            'page' => '2',
            'perPage' => '25',
            'sort' => 'createdAt',
            'order' => 'desc',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
javascript
const url = new URL(
    "https://api.lindris.com/api/campaigns"
);

const params = {
    "status": "sent",
    "page": "2",
    "perPage": "25",
    "sort": "createdAt",
    "order": "desc",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_KEY}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Responses

json
{
   "data": [
      {
         "id": 123,
         "name": "My Newsletter",
         "status": "draft",
         "builderReviewed": false,
         "createdAt": "2024-01-19T08:30:00+00:00",
         "scheduledAt": null,
         "sentAt": null,
         "links": {
            "campaignUrl": "https://app.lindris.com/campaigns/123",
            "editorUrl": "https://app.lindris.com/emails/campaigns/123"
         }
      }
   ],
   "meta": {
      "currentPage": 1,
      "lastPage": 1,
      "from": 1,
      "to": 1,
      "total": 1,
      "perPage": 10,
      "path": "/api/campaigns"
   },
   "links": {
      "next": null,
      "prev": null,
      "first": "/api/campaigns?page=1",
      "last": "/api/campaigns?page=1"
   }
}
json
{
   "message": "Unauthenticated"
}

Create campaign draft

POST api/campaigns

Create a new campaign draft. You may optionally provide a templateId to pre-populate the email content from a saved template. To duplicate an existing campaign, use POST /campaigns/{id}/clone.

Request Body

  • name string required - The campaign name. Example: My Newsletter
  • templateId string optional - The ID of an email template to use as the starting content.

Request

bash
curl --request POST \
    "https://api.lindris.com/api/campaigns" \
    --header "Authorization: Bearer {YOUR_API_KEY}" \
    --header "Content-Type: application/json" \
    --data "{
    \"name\": \"My Newsletter\"
}"
php
$client = new \GuzzleHttp\Client();
$url = 'https://api.lindris.com/api/campaigns';
$response = $client->post(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_KEY}',
            'Content-Type' => 'application/json',
        ],
        'json' => [
            'name' => 'My Newsletter',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
javascript
const url = new URL(
    "https://api.lindris.com/api/campaigns"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_KEY}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "name": "My Newsletter"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Responses

json
{
   "data": {
      "id": 123,
      "name": "My Newsletter",
      "status": "draft",
      "subject": "Welcome to our newsletter",
      "previewText": "Read our latest updates inside",
      "sender": {
         "name": "Acme Corp",
         "email": "[email protected]"
      },
      "replyTo": {
         "name": "Acme Support",
         "email": "[email protected]"
      },
      "builderReviewed": false,
      "createdAt": "2024-01-19T08:30:00+00:00",
      "scheduledAt": null,
      "sentAt": null,
      "links": {
         "campaignUrl": "https://app.lindris.com/campaigns/123",
         "editorUrl": "https://app.lindris.com/emails/campaigns/123"
      }
   }
}
json
{
   "message": "The name field is required.",
   "errors": {
      "name": [
         "The name field is required."
      ]
   }
}
json
{
   "message": "The selected template does not exist.",
   "errors": {
      "templateId": [
         "The selected template does not exist."
      ]
   }
}

Clone campaign

POST api/campaigns/{id}/clone

Duplicate an existing campaign into a new draft, copying its content and targeting.

URL Parameters

  • id integer required - The ID of the campaign to duplicate. Example: 123

Request Body

  • name string optional - Name for the new campaign. Defaults to a "Copy of …" name when omitted. Example: My Newsletter (copy)

Request

bash
curl --request POST \
    "https://api.lindris.com/api/campaigns/123/clone" \
    --header "Authorization: Bearer {YOUR_API_KEY}" \
    --header "Content-Type: application/json" \
    --data "{
    \"name\": \"My Newsletter (copy)\"
}"
php
$client = new \GuzzleHttp\Client();
$url = 'https://api.lindris.com/api/campaigns/123/clone';
$response = $client->post(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_KEY}',
            'Content-Type' => 'application/json',
        ],
        'json' => [
            'name' => 'My Newsletter (copy)',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
javascript
const url = new URL(
    "https://api.lindris.com/api/campaigns/123/clone"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_KEY}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "name": "My Newsletter (copy)"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Responses

json
{
   "data": {
      "id": 123,
      "name": "My Newsletter",
      "status": "draft",
      "subject": "Welcome to our newsletter",
      "previewText": "Read our latest updates inside",
      "sender": {
         "name": "Acme Corp",
         "email": "[email protected]"
      },
      "replyTo": {
         "name": "Acme Support",
         "email": "[email protected]"
      },
      "builderReviewed": false,
      "createdAt": "2024-01-19T08:30:00+00:00",
      "scheduledAt": null,
      "sentAt": null,
      "links": {
         "campaignUrl": "https://app.lindris.com/campaigns/123",
         "editorUrl": "https://app.lindris.com/emails/campaigns/123"
      }
   }
}
json
{
   "message": "Campaign not found"
}

Get campaign details

GET api/campaigns/{id}

Retrieve a single campaign by its ID, including its builder-reviewed status and current campaign status.

URL Parameters

  • id integer required - The campaign ID. Example: 123

Response Fields

  • data array
    • id integer optional - The unique identifier for the campaign. Example: 123
    • name string optional - The campaign name. Example: My Newsletter
    • status string optional - The current campaign status. Enum: draft,sent,scheduled,sending,preparing,paused,failed Example: draft
    • subject string optional - The email subject line. Example: Welcome to our newsletter
    • previewText string optional - The email preview text shown in inbox previews. Example: Read our latest updates
  • sender object optional - Sender details.
    • name string optional - The sender display name. Example: Acme Corp
    • email string optional - The sender email address. No-example
  • replyTo object optional - Reply-to details.
    • name string optional - The reply-to display name. Example: Acme Support
    • email string optional - The reply-to email address. No-example
    • builderReviewed boolean optional - Whether the email content has been reviewed in the email builder. Example: false
    • createdAt string optional - ISO 8601 datetime when the campaign was created. Example: 2024-01-19T08:30:00+00:00
    • scheduledAt string optional - ISO 8601 datetime when the campaign is scheduled to send (null if not scheduled). Example: 2024-02-01T10:00:00+00:00
    • sentAt string optional - ISO 8601 datetime when the campaign finished sending (null if not sent). Example: 2024-01-25T14:32:00+00:00
  • links object optional - UI handoff links for this campaign.

Request

bash
curl --request GET \
    --get "https://api.lindris.com/api/campaigns/123" \
    --header "Authorization: Bearer {YOUR_API_KEY}" \
    --header "Content-Type: application/json"
php
$client = new \GuzzleHttp\Client();
$url = 'https://api.lindris.com/api/campaigns/123';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_KEY}',
            'Content-Type' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
javascript
const url = new URL(
    "https://api.lindris.com/api/campaigns/123"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_KEY}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Responses

json
{
   "data": {
      "id": 123,
      "name": "My Newsletter",
      "status": "draft",
      "subject": "Welcome to our newsletter",
      "previewText": "Read our latest updates inside",
      "sender": {
         "name": "Acme Corp",
         "email": "[email protected]"
      },
      "replyTo": {
         "name": "Acme Support",
         "email": "[email protected]"
      },
      "builderReviewed": false,
      "createdAt": "2024-01-19T08:30:00+00:00",
      "scheduledAt": null,
      "sentAt": null,
      "links": {
         "campaignUrl": "https://app.lindris.com/campaigns/123",
         "editorUrl": "https://app.lindris.com/emails/campaigns/123"
      }
   }
}
json
{
   "message": "Campaign not found"
}

Update campaign

PUT api/campaigns/{id}

Update one or more fields of an existing campaign. All fields are optional, but at least one must be provided.

URL Parameters

  • id integer required - The campaign ID. Example: 123

Request Body

  • name string optional - The campaign name.
    • Example: My Updated Newsletter
  • subject string optional - The email subject line.
    • Example: Big sale — don't miss out!
  • previewText string optional - The email preview text.
    • Example: Up to 50% off this weekend only
  • sender object optional - Sender configuration.

Example: []

* `name` <small class="prop-details"> string _optional_</small> - The sender display name.
  Example: `Acme Marketing`
* `email` <small class="prop-details"> string _optional_</small> - The sender email address.
  • replyTo object optional - Reply-to configuration.

Example: []

* `name` <small class="prop-details"> string _optional_</small> - The reply-to display name.
  Example: `Acme Support`
* `email` <small class="prop-details"> string _optional_</small> - The reply-to email address.

Request

bash
curl --request PUT \
    "https://api.lindris.com/api/campaigns/123" \
    --header "Authorization: Bearer {YOUR_API_KEY}" \
    --header "Content-Type: application/json" \
    --data "{
    \"name\": \"My Updated Newsletter\",
    \"subject\": \"Big sale — don\'t miss out!\",
    \"previewText\": \"Up to 50% off this weekend only\",
    \"sender\": {
        \"name\": \"Acme Marketing\"
    },
    \"replyTo\": {
        \"name\": \"Acme Support\"
    }
}"
php
$client = new \GuzzleHttp\Client();
$url = 'https://api.lindris.com/api/campaigns/123';
$response = $client->put(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_KEY}',
            'Content-Type' => 'application/json',
        ],
        'json' => [
            'name' => 'My Updated Newsletter',
            'subject' => 'Big sale — don\'t miss out!',
            'previewText' => 'Up to 50% off this weekend only',
            'sender' => [
                'name' => 'Acme Marketing',
            ],
            'replyTo' => [
                'name' => 'Acme Support',
            ],
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
javascript
const url = new URL(
    "https://api.lindris.com/api/campaigns/123"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_KEY}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "name": "My Updated Newsletter",
    "subject": "Big sale — don't miss out!",
    "previewText": "Up to 50% off this weekend only",
    "sender": {
        "name": "Acme Marketing"
    },
    "replyTo": {
        "name": "Acme Support"
    }
};

fetch(url, {
    method: "PUT",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Responses

json
{
   "data": {
      "id": 123,
      "name": "My Newsletter",
      "status": "draft",
      "subject": "Welcome to our newsletter",
      "previewText": "Read our latest updates inside",
      "sender": {
         "name": "Acme Corp",
         "email": "[email protected]"
      },
      "replyTo": {
         "name": "Acme Support",
         "email": "[email protected]"
      },
      "builderReviewed": false,
      "createdAt": "2024-01-19T08:30:00+00:00",
      "scheduledAt": null,
      "sentAt": null,
      "links": {
         "campaignUrl": "https://app.lindris.com/campaigns/123",
         "editorUrl": "https://app.lindris.com/emails/campaigns/123"
      }
   }
}
json
{
   "message": "Campaign not found"
}
json
{
   "message": "At least one field must be provided for update.",
   "errors": {
      "_body": [
         "At least one field must be provided for update."
      ]
   }
}
json
{
   "message": "Only draft campaigns can be updated.",
   "errors": {
      "status": [
         "Only draft campaigns can be updated."
      ]
   }
}

Delete campaign

DELETE api/campaigns/{id}

Permanently delete a campaign by its ID. Campaigns of any status can be deleted (draft, scheduled, paused, sent, failed) except one that is actively sending, which is rejected to avoid disrupting an in-progress send.

URL Parameters

  • id integer required - The campaign ID. Example: 123

Request

bash
curl --request DELETE \
    "https://api.lindris.com/api/campaigns/123" \
    --header "Authorization: Bearer {YOUR_API_KEY}" \
    --header "Content-Type: application/json"
php
$client = new \GuzzleHttp\Client();
$url = 'https://api.lindris.com/api/campaigns/123';
$response = $client->delete(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_KEY}',
            'Content-Type' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
javascript
const url = new URL(
    "https://api.lindris.com/api/campaigns/123"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_KEY}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "DELETE",
    headers,
}).then(response => response.json());

Responses

text
(No response body)
json
{
   "message": "Campaign not found"
}
json
{
   "message": "Campaigns that are currently sending cannot be deleted.",
   "errors": {
      "status": [
         "Campaigns that are currently sending cannot be deleted."
      ]
   }
}