Schedule Campaign
Schedule a ready campaign to send at a future time.
The same rules as Send Campaign apply: the campaign must be in
a startable status — draft, failed, or scheduled — and pass its readiness
report. A non-startable status returns 409 CAMPAIGN_NOT_SENDABLE; a campaign
that is not yet ready returns 422 CAMPAIGN_NOT_READY with the outstanding
requirements in details. See Readiness.
Scheduling an already-scheduled campaign reschedules it to the new time.
On success the campaign moves to scheduled with scheduled_at set, and the full
campaign detail is returned. The send happens later, at the scheduled time, in the
background.
Request
POST /campaigns/{uuid}/schedule
Path Parameters
| Parameter | Type | Description |
|---|---|---|
uuid | string | Campaign's UUID |
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
scheduled_at | string | Yes | When to send the campaign — an ISO 8601 instant with an explicit offset or Z, in the future. A missing, malformed, or past value returns 422 VALIDATION_ERROR. |
There is no timezone parameter — scheduled_at is interpreted in UTC. Provide the
instant with an explicit offset or Z.
Example Request
curl -X POST "https://email.easy.tools/api/v1/campaigns/550e8400-e29b-41d4-a716-446655440000/schedule" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"scheduled_at": "2026-07-01T09:00:00Z"
}'
Response
Success Response (200 OK)
Returns the full campaign, identical in shape to Get Campaign,
with status now scheduled and scheduled_at set.
{
"data": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "Spring Sale",
"status": "scheduled",
"subject": "Up to 40% off this week",
"preheader": "Our biggest sale of the season",
"from_name": "Acme",
"reply_to": "support@acme.com",
"from_identity": "8f14e45f-ceea-467a-9575-1a1b2c3d4e5f",
"from_email": "hello@acme.com",
"content": "## Spring sale\n\nUp to **40% off**. [Shop now](https://acme.com/sale)",
"content_editable_via_api": true,
"content_overwrite_required": false,
"audience": {
"list_uuid": "660e8400-e29b-41d4-a716-446655440001",
"segment_uuid": null
},
"readiness": {
"can_send": true,
"missing": []
},
"created_at": "2026-06-24T10:00:00Z",
"updated_at": "2026-06-26T08:00:00Z",
"last_updated_at": "2026-06-24T10:05:00Z"
}
}
The scheduled_at you set is returned by List Campaigns. See
Get Campaign for the full field reference.
Error Responses
Not Found Error (404)
{
"error": {
"code": "RESOURCE_NOT_FOUND",
"message": "Campaign with UUID '550e8400-e29b-41d4-a716-446655440000' not found"
}
}
Conflict Error (409 — Not Sendable)
The campaign's status is not startable. Only a draft, failed, or scheduled
campaign can be scheduled.
{
"error": {
"code": "CAMPAIGN_NOT_SENDABLE",
"message": "Campaign cannot be scheduled because of its current status"
}
}
Conflict Error (409 — Transition In Progress)
Another change to the same campaign is already in flight. Retry after a moment.
{
"error": {
"code": "CAMPAIGN_TRANSITION_IN_PROGRESS",
"message": "Another transition is already in progress for this campaign"
}
}
Validation Error (422 Unprocessable Entity)
scheduled_at is missing, malformed, or not in the future.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "The given data was invalid",
"details": {
"scheduled_at": ["The scheduled at must be a date after now."]
}
}
}
Validation Error (422 — Not Ready)
The campaign does not meet every requirement to be sent. details carries the
readiness report: can_send is false and missing lists the outstanding
requirements. See Readiness for each requirement and how
to satisfy it.
{
"error": {
"code": "CAMPAIGN_NOT_READY",
"message": "Campaign is not ready to be scheduled",
"details": {
"can_send": false,
"missing": ["sender_email", "content", "audience"]
}
}
}