# Dates and scheduling

The date on a campaign draft is a calendar anchor, not a send time — nothing is scheduled from the API. This page covers the three accepted date forms, which timezone each one is read in, the separate time field, and why unparseable input is refused rather than guessed at.

**Language:** en
**Audience:** developer
**TLDR:** date places the draft on the dashboard calendar and schedules nothing. It accepts an ISO 8601 datetime with an offset (honoured as an exact instant), a date and time without an offset (read in the project's timezone), or a bare day (project timezone, 19:00). Integrations should send the offset form. time (HH:MM) is an alternative to putting the hour in date; sending both is an error. Maximum one year ahead.
**Search keywords:** date, schedule, scheduling, send time, when, timezone, time zone, offset, ISO 8601, UTC, calendar, plan a campaign, future campaign
**Related pages:** /developers/product-api/campaigns/creating-a-draft, /developers/product-api/campaigns/estimating-and-deleting, /platform/en/campaigns/creating-a-campaign
**Docs index (every page):** https://docs.instasent.com/llms.txt
**This zone's index:** https://docs.instasent.com/developers/product-api/llms-full.txt
**This page:** https://docs.instasent.com/developers/product-api/campaigns/scheduling/ (HTML) · https://docs.instasent.com/developers/product-api/campaigns/scheduling.md (Markdown)

`date` places a campaign draft on the dashboard calendar so a marketer opening the project can see what is coming and when it was meant to go out. It is a **planning anchor**, and setting it arms nothing.

> **Warning**: **Nothing is scheduled by this endpoint, at any precision.** A date to the minute, with a timezone offset, still produces a draft that will not send. Arming a campaign happens in the dashboard, at the review step, after a human has seen the estimate. There is no API field that skips it.
> 
> That estimate can now be [started from the API](/developers/product-api/campaigns/estimating-and-deleting#estimating-a-draft), which changes nothing here: knowing what a campaign would cost is not a step towards sending it, and the confirmation at the review step is still a person's.

`date` is also entirely optional: omit it and the draft simply carries no date, which is the right choice when your integration knows what to say but not yet when.

## The three accepted forms

The precision you send is the precision that is stored — and **the input decides which timezone applies**:

| Form                     | Example                                                                      | Interpreted in                                                |
| ------------------------ | ---------------------------------------------------------------------------- | ------------------------------------------------------------- |
| ISO 8601 with an offset  | `2026-06-15T09:30:00+02:00`, `2026-06-15T09:30:00Z`, `2026-06-15T09:30+0200` | the offset you sent — the project's timezone is not consulted |
| Date and time, no offset | `2026-06-15T09:30`, `2026-06-15 09:30`                                       | the project's timezone                                        |
| Day only                 | `2026-06-15`                                                                 | the project's timezone, at 19:00                              |

The project's timezone falls back to the organization's when the project does not set one of its own.

### Integrations should send the offset form

```json
{
  "date": "2026-06-15T09:30:00+02:00"
}
```

It is the only form that means the same instant on both ends. A server in another region, a container running in UTC, a laptop on summer time — none of them change what that string denotes. The two offset-less forms are a convenience for a human typing a date into your UI, where "half past nine" naturally means half past nine where the audience lives; they are the wrong choice for a machine that already knows the exact moment.

## Sending the time separately

Some callers hold the day and the time apart — a date picker and a time picker, two columns in a spreadsheet — and joining them into an ISO string is busywork. `time` exists for exactly that:

```json
{
  "date": "2026-06-15",
  "time": "09:30"
}
```

`time` is `HH:MM`, read in the project's timezone, and it replaces the 19:00 default a bare day would otherwise get.

> **Warning**: **Sending `time` alongside a `date` that already carries an hour is an error**, not a precedence rule. `{"date": "2026-06-15T09:30", "time": "11:00"}` is refused with `invalid-date`. Two answers to the same question is how an integration ends up anchored at the wrong hour and never finds out why — so the API asks you to pick one instead of quietly choosing for you.

## Parsing is strict on purpose

The accepted forms above are an allow-list. Anything else is refused with `invalid-date` rather than interpreted:

| Input                 | Why it is refused                                                                                                                                |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `15/06/2026`          | Ambiguous. Depending on the separator and locale it reads as day 15 or month 15 — an API that silently picks one is worse than one that says no. |
| `tomorrow`, `+1 week` | Relative expressions are not dates. Resolve them on your side, where you know the user's timezone.                                               |
| `2026-13-45`          | Out of range. It is not rolled over into February of the following year.                                                                         |
| `2026-06-15T25:99`    | Out of range. It is not rolled over into the next day.                                                                                           |

The overflow cases are the ones worth designing around: a caller that computed a date wrongly gets told, at the moment of the call, instead of finding a campaign anchored on a day nobody chose.

## The one-year horizon

A campaign date must be **less than a year from now**. A date beyond that is understood perfectly well and then refused by the campaign itself, so it comes back as a field-level `422` keyed by the campaign's own field name (`campaignAt`) rather than as an `invalid-date` code:

```json
{
  "errors": {
    "fields": {
      "campaignAt": ["This value should be less than Jun 15, 2027, 12:00 AM."]
    }
  }
}
```

## Scheduling the actual send

The send time is chosen in the dashboard, on the campaign's **Review & schedule** step, along with the delivery settings that surround it. The reader-facing walkthrough is [Creating a campaign](/platform/en/campaigns/creating-a-campaign); [Delivery settings](/platform/en/campaigns/delivery-settings) covers the options that shape how the send runs once it is armed.

For an integration this means the handover is clean: you supply the intent — who, what, and the day it is meant for — and a person supplies the confirmation.

## What's next

- [Creating a draft](/developers/product-api/campaigns/creating-a-draft) - The endpoint contract, the full request body, limits and error codes.
- [Audience targeting](/developers/product-api/campaigns/audience) - Segments, inline filters and counting the reach up front.
- [Message content](/developers/product-api/campaigns/message) - Copy, senders, RCS buttons, SMS fallback and languages.

---

This is one page of the Instasent documentation. For the complete machine-readable index of every guide and API reference, fetch https://docs.instasent.com/llms.txt — start there for full context.
