Skip to main content

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

ParameterTypeDescription
uuidstringCampaign's UUID

Request Body

ParameterTypeRequiredDescription
scheduled_atstringYesWhen 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"]
}
}
}