# Emails and notices

> The acknowledgment, trial, renewal, price-change and cancellation emails automatic-renewal laws require, when each must be sent, how to check your templates, and how Checkbox Notices can send them for you.

Automatic-renewal laws do not stop at the checkout. Depending on the plan and the subscriber's state, you must send:

| Email | When | Check |
|---|---|---|
| Acknowledgment | Right after sign-up: the terms, the cancellation policy and how to cancel | `confirmation.*` |
| Trial ending | Before a free trial converts to paid, inside each state's window | `reminder.trial_ending` |
| Renewal reminder | Before renewals of longer terms (a year or more; shorter in some states) | `reminder.annual_renewal` |
| Yearly terms | Once a year for monthly or other short-term plans, in some states | `reminder.annual_terms_notice` |
| Price change | Before a higher price is first charged | `reminder.price_change` |
| Cancellation confirmation | After a subscriber cancels | `cancel.confirmation` |

## When to send them {#schedule}

Windows differ by state and plan (trial length, term length, payment method). Ask for the exact dates for a
subscription; Checkbox intersects every applicable state's window and, where they conflict, returns the fewest sends
that satisfy all of them:

```curl
curl https://app.checkbox.site/v1/checks/notice_schedule \
  -u "$CHECKBOX_SECRET_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
    "terms": {
      "merchant_name": "Joybox",
      "price": 99,
      "interval": "year",
      "trial_days": 35,
      "cancel_url": "https://joybox.example/account/cancel"
    },
    "start_date": "2026-11-02",
    "jurisdictions": ["US-CA", "US-NY"]
  }'
```
```node
import Checkbox from '@checkbox-site/cli';

const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);

const schedule = await checkbox.checks.noticeSchedule({
  terms: { merchant_name: 'Joybox', price: 99, interval: 'year', trial_days: 35, cancel_url: 'https://joybox.example/account/cancel' },
  start_date: '2026-11-02',
  jurisdictions: ['US-CA', 'US-NY'],
});
for (const n of schedule.notices) console.log(n.kind, n.send_date, n.citations.join('; '));
```
```python
import os
from checkbox import Checkbox

checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])

schedule = checkbox.checks.notice_schedule(
    terms={"merchant_name": "Joybox", "price": 99, "interval": "year", "trial_days": 35,
           "cancel_url": "https://joybox.example/account/cancel"},
    start_date="2026-11-02",
    jurisdictions=["US-CA", "US-NY"],
)
for n in schedule["notices"]:
    print(n["kind"], n["send_date"], "; ".join(n["citations"]))
```

Each notice has `send_date` / `send_at`, the window (`window_opens_at` … `window_closes_at`), the jurisdictions and
citations it satisfies.

## Check a template {#check-template}

```curl
curl https://app.checkbox.site/v1/checks/email \
  -u "$CHECKBOX_SECRET_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "trial_reminder",
    "subject": "Your trial ends soon",
    "text": "Hi! Your free trial ends on December 4. Thanks for trying Joybox.",
    "terms": {
      "merchant_name": "Joybox",
      "price": 19.99,
      "interval": "month",
      "trial_days": 14,
      "cancel_url": "https://joybox.example/account/cancel"
    }
  }'
```
```node
import Checkbox from '@checkbox-site/cli';

const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);

const result = await checkbox.checks.email({
  kind: 'trial_reminder',
  subject: 'Your trial ends soon',
  text: 'Hi! Your free trial ends on December 4. Thanks for trying Joybox.',
  terms: { merchant_name: 'Joybox', price: 19.99, interval: 'month', trial_days: 14, cancel_url: 'https://joybox.example/account/cancel' },
});
console.log(result.verdict);
console.log(result.template.subject);
console.log(result.template.merge_tags);
```
```python
import os
from checkbox import Checkbox

checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])

result = checkbox.checks.email(
    kind="trial_reminder",
    subject="Your trial ends soon",
    text="Hi! Your free trial ends on December 4. Thanks for trying Joybox.",
    terms={"merchant_name": "Joybox", "price": 19.99, "interval": "month", "trial_days": 14,
           "cancel_url": "https://joybox.example/account/cancel"},
)
print(result["verdict"])
print(result["template"]["subject"])
print(result["template"]["merge_tags"])
```

When the email fails, `template` holds a compliant subject, text and HTML with merge tags (for example
`{{trial_end_date}}`) for you to fill per subscriber. Email checks judge content; real send timing is judged by
monitoring.

## Let Checkbox see the real emails {#monitor}

- **BCC** each lifecycle email to the site's inbound address (`install.inbound_email` on the site), **labelled with its
  kind** so Checkbox never has to guess: plus-address it (`<key>+annual_terms@…`) or add the header
  `X-Checkbox-Kind: annual_terms`. Kinds: `acknowledgment`, `trial_reminder`, `renewal_reminder`, `price_change`,
  `annual_terms`, `charge_notice`, `cancellation_confirmation` (the same names `checkEmail`, `verifyTask` and the plan
  use; `trial_ending` is accepted as an alias, as in Notices). Unlabelled mail is classified by its content.
- Run a [test subscription](https://checkbox.site/docs/guides/test-runs): Checkbox subscribes with its own inbox and moves a test clock
  through trial end and renewal, so it receives every email your code sends and knows exactly when it was sent.

## Checkbox Notices {#notices}

Checkbox can send the required notices for you, from your brand, timed from the legal catalog, and record each delivery
as evidence. Turn it on per site with [`updateNoticeSettings`](https://checkbox.site/docs/api/notices#updateNoticeSettings) (live mode needs
an activated account). Notices send email only: where New York requires reminders "in the manner the consumer
selected", the plan asks you to attest that subscribers chose email; and New York's price-increase consent or refund
right cannot be provided by any notice, so it stays a question for you.
