Skip to content

Recurring Templates

Recurring templates automatically generate invoices, bills or journal entries on a schedule. Set up a template once and DayZero creates the documents at the configured frequency.

Create a Recurring Template

A template has a schedule (top-level fields) and the document to generate (template_data):

bash
curl -X POST "https://api.ondayzero.com/api/v1/recurring" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme monthly retainer",
    "recurrence_type": "invoice",
    "customer_id": "CUSTOMER_UUID",
    "frequency": "monthly",
    "day_of_month": 1,
    "start_date": "2026-11-01",
    "days_until_due": 30,
    "auto_send": false,
    "template_data": {
      "description": "Monthly retainer",
      "line_items": [
        {
          "description": "Monthly retainer",
          "quantity": 1,
          "unit_price": 250000
        }
      ]
    }
  }'

unit_price is in cents. 250000 = $2,500.00 per month.

The response is the template (status 201), trimmed here:

json
{
  "success": true,
  "data": {
    "id": "0198a2c4-0000-7d3a-9a51-3f6f0c1d2e50",
    "name": "Acme monthly retainer",
    "recurrence_type": "invoice",
    "status": "active",
    "frequency": "monthly",
    "start_date": "2026-11-01",
    "next_occurrence": "2026-11-01",
    "last_generated": null,
    "occurrences_generated": 0,
    "days_until_due": 30,
    "auto_send": false,
    "customer": { "id": "0198a2c4-0000-7d3a-9a51-3f6f0c1d2e20", "name": "Acme Corp" },
    "frequency_display": "Monthly",
    "days_until_next": 18
  }
}

start_date and end_date cannot be in the past. You can also create a template as part of an invoice or bill: send a recurring object (frequency, start_date, and optional name, day_of_month, day_of_week, days_until_due, end_date, max_occurrences) on POST /api/v1/invoices or POST /api/v1/bills (or the matching PUT). On invoice create, the invoice you are creating counts as the schedule's first occurrence, so the template generates the next one a period later.

A recurring bill:

bash
curl -X POST "https://api.ondayzero.com/api/v1/recurring" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Office rent",
    "recurrence_type": "bill",
    "vendor_id": "VENDOR_UUID",
    "frequency": "monthly",
    "day_of_month": 1,
    "days_until_due": 15,
    "start_date": "2026-11-01",
    "template_data": {
      "description": "Office rent for 123 Main St",
      "amount": 350000
    }
  }'

Schedule fields

Field Required Description
name Yes Template name
recurrence_type Yes invoice, bill or journal_entry
frequency Yes daily, weekly, biweekly, monthly, quarterly, annually
start_date Yes First generation date
customer_id For invoices Customer to bill
vendor_id For bills Vendor the bill is from
day_of_month No 1–31 for monthly/quarterly/annually; clamps to the last day of shorter months. Defaults to the day in start_date
day_of_week No 0 = Monday … 6 = Sunday for weekly/biweekly. Defaults to the weekday of start_date
days_until_due No Days from generation to due date, 0-365 (default 30)
end_date / max_occurrences No Stop after a date or a count — whichever comes first. Both null = indefinite
auto_send No Invoice templates only. Stored on the template (default false). Generated invoices are always created as draft; see the note under template_data
currency No USD (default), CAD, AUD, EUR, GBP
notes No Free-text notes, up to 1,000 characters
contract_id No Invoice templates only — routes generated invoices into the contract's billing tallies

template_data by type

Type Keys
invoice Either line_items (same shape as invoice line items; the total is calculated) or total (cents), plus optional description and project_id. Generated invoices are created as draft with the next invoice number, and are not finalized or emailed automatically
bill amount (cents, required) and optional description. Generated bills are created as forecasted, type: recurring, with expected_amount set from amount
journal_entry line_entries (at least two balanced debit/credit lines, same shape as journal entry lines) and description, both required

Customers and vendors are validated when the template is created, and again at generation time: if the customer or vendor has since been removed, that occurrence fails.

List Templates

bash
curl "https://api.ondayzero.com/api/v1/recurring?recurrence_type=invoice&status=active" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID"

Filter Parameters

Parameter Type Description
recurrence_type string invoice, bill or journal_entry
status string active, paused, completed, cancelled
customer_id UUID Filter invoice templates by customer
vendor_id UUID Filter bill templates by vendor
search string Match on name, description, frequency, status or counterparty

Plus the standard pagination parameters. Shortcut endpoints are also available (each takes status and its counterparty filter plus pagination):

  • GET /api/v1/recurring/invoices — only invoice templates (customer_id)
  • GET /api/v1/recurring/bills — only bill templates (vendor_id)

GET /api/v1/recurring/{template_id} returns one template. Each template includes status, next_occurrence, last_generated, occurrences_generated, customer / vendor summaries, contract_id, and computed fields such as frequency_display and days_until_next.

POST /api/v1/recurring/suggest-templates asks the AI to find repeating invoices and bills that could become templates.

Manage Template Lifecycle

Status rules: a template starts active. Only an active template can be paused or skipped, only a paused one can be resumed, and a completed or cancelled template can no longer be cancelled or updated (each returns 400). A template becomes completed when it reaches end_date or max_occurrences.

Pause

bash
curl -X POST "https://api.ondayzero.com/api/v1/recurring/{template_id}/pause" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID"

Resume

Resuming recalculates the next occurrence.

bash
curl -X POST "https://api.ondayzero.com/api/v1/recurring/{template_id}/resume" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID"

Cancel

bash
curl -X POST "https://api.ondayzero.com/api/v1/recurring/{template_id}/cancel" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID"

Cancelling is permanent (status cancelled); use pause if you may want to resume. DELETE /api/v1/recurring/{template_id} removes the template entirely; documents it already generated are kept.

Skip Next Occurrence

Advances next_occurrence to the following scheduled date without generating a document (active templates only). The response has skipped_date, next_occurrence and message. If the following date falls after end_date, the template becomes completed.

bash
curl -X POST "https://api.ondayzero.com/api/v1/recurring/{template_id}/skip" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID"

Update

PUT /api/v1/recurring/{template_id} changes name, currency, frequency, days_until_due, day_of_month, day_of_week, end_date, max_occurrences, notes, template_data, auto_send, customer_id (invoice templates only), vendor_id (bill templates only) and contract_id (invoice templates only); changes apply from the next generation onward. template_data.amount and template_data.total must be positive. recurrence_type and start_date cannot be changed — clone instead. Completed and cancelled templates cannot be updated.

View Generation History

See the documents generated from a template (limit is 1-100, default 50). The response has template_id, template_name, document_type, total_generated and items; each item has id, document_type, status, number, description, amount (cents), due_date and created_at, plus customer_name (invoices) or vendor_name (bills):

bash
curl "https://api.ondayzero.com/api/v1/recurring/{template_id}/history?limit=10" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID"

Clone a Template

Copy a template, optionally pointing it at a different customer or vendor and a new start date. name defaults to the original name plus (Copy) and start_date defaults to today. The clone starts active with 0 occurrences generated:

bash
curl -X POST "https://api.ondayzero.com/api/v1/recurring/{template_id}/clone" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID" \
  -H "Content-Type: application/json" \
  -d '{"name": "Globex monthly retainer", "customer_id": "OTHER_CUSTOMER_UUID", "start_date": "2026-12-01"}'

Upcoming Scheduled Invoices

GET /api/v1/invoices/scheduled?days=90 projects the invoices that will auto-draft, from active recurring invoice templates and upcoming contract billing periods. It is read-only: nothing is created and no template or contract changes. days is 1-730 (default 90) and only bounds items with no end date; a template with an end_date is projected in full through that date. The response is {"items": [...]} sorted by date, each with scheduled_date, amount_cents, customer_name, source (recurring_template or contract), source_id, description, and, when they resolve, project_id, project_name, contract_id and contract_number. The Scheduled tab in the app asks for 400 days.

Common errors

Status Cause Fix
422 start_date or end_date in the past, day_of_month outside 1-31, day_of_week outside 0-6, days_until_due outside 0-365 Fix the field named in errors
400 Pausing or skipping a template that is not active, resuming one that is not paused, or cancelling or updating a completed / cancelled one Check status first
404 Template id wrong or from another business List with GET /api/v1/recurring