Cancel a recurring series
A series ends by date, and there is no cancelled state. The series bills up to end_date: the un-issued occurrence the date falls in is cut and prorated, un-issued occurrences past it are dropped, and what was ISSUED past it is handed back with credit notes. Those are queued and booked by a job, so the request does not wait for the platform: credit_notes lists each as it stands (queued, or booked). An end set to today or to a day that has passed issues the occurrences that are due at once. A series that has not started and has issued nothing is deleted instead (discarded). The body may be left out. **Sending the same end date again is safe**: it is never refused, writes no second credit note, states the credit notes as they now stand, and has any that is not booked attempted again. A different date is refused once the end has passed (END_HAS_PASSED) or a credit note has settled it (END_CREDITED).
Authorization
bearerAuth An API key minted by an admin under Settings → Developers. It is bound to one company and has a scope: read, or read_write. A request without one, or with one that is not ours, is answered 401 and metered by its client address (x-rate-limits).
In: header
Path Parameters
The record's id, or ext:<external_id> for the record that carries your own key.
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/recurring-series/string/cancel" \ -H "Content-Type: application/json" \ -d '{}'{ "object": "recurring_series", "id": "string", "external_id": "string", "customer_id": "string", "customer_name": "string", "currency": "string", "frequency": "monthly", "start_date": "string", "end_date": "string", "issue_timing": { "mode": "start-of-period" }, "title": "string", "use_billing_period_as_title": true, "layout_ref": "string", "status": "draft", "cancelled_at": "string", "created_at": "string", "updated_at": "string", "lines": [ { "id": "string", "product_id": "string", "product_number": "string", "product_name": "string", "recognition_method": "value", "agreed_value": 0, "hourly_rate": 0, "discount": 0, "description_override": "string", "position": -9007199254740991, "assignees": [ { "user_id": "string", "distribution_percentage": 0, "hourly_rate_override": 0, "removed": true } ] } ], "discarded": true, "unchanged": true, "credit_notes": [ { "id": "string", "invoice_id": "string", "state": "queued" } ], "dropped_occurrences": [ { "period_from": "string", "period_to": "string", "work_registrations": -9007199254740991 } ]}Create a recurring series POST
A series is Tabba’s own record: nothing is asked of the accounting platform until one of its occurrences is issued. With an `external_id` no series carries, the series is created active with its lines, each complete, and the answer is 201; occurrences whose period has started are invoices at once. With one a series carries, the header of that series is saved, as `PATCH` saves it, and the answer is 200: **its lines are left as they are**. A line has a timeline of its own, so the lines of a series that exists are changed through the line routes. Two creates under one `external_id` at the same moment make one series.
Add a line to a recurring series POST
With `this-and-following` the line is a recurring one from the occurrence `period` names (the start of the series where it is left out): earlier occurrences never see it. With `this-only` it is a one-time line on that one occurrence. The line is placed after the lines the occurrence has: a new line never moves one that was there. Occurrences that are already invoices, and not issued, follow the change. **Not idempotent**: a line carries no key of its own, and adding twice adds two.