Repeat a visit on a job
POST/api/v1/jobs/{job_id}/visit_series
Creates a series that repeats every N days, weeks or months, or every weekday, and schedules its visits eight weeks ahead. A nightly job keeps extending it. Generated visits are ordinary visits with visit_series_id set. With season_from_month and season_to_month the series runs for only part of the year: dates outside those months are skipped, and the rhythm is still counted from starts_on, so it returns on the dates it would have had. A season in which no visit would ever fall is refused with 422 season_has_no_visits. A series that ends on a date is removed overnight once every visit up to that date has been booked and none is still scheduled or in progress. Its visits stay and lose their link.
- Needs an API key, and runs with the access of the member who made the key.
- Send an
Idempotency-Key. The same key with the same request within 24 hours gives the first answer again and changes nothing. - A connected AI assistant can use it too, as
createVisitSeries.
Parameters
In the address
job_idstring (uuid)required
Headers
Idempotency-KeystringrequiredUnique user-scoped key for safely retrying this mutation for 24 hours.
At least 1 character. Up to 200 characters.
Request body
Sent as application/json.
visit_seriesobjectrequiredFields(12)
lock_versionintegerAt least 0.
intervalintegerrequiredunitstringrequired`weekday` is Monday to Friday, one visit per working day, and needs an interval of 1.
One of: day, weekday, week, month.
occurrencesintegerEnd after this many visits from `starts_on`; dates outside a season are not counted. Stored as `ends_on`.
At least 1. At most 500. Write only.
starts_onstring (date)requiredends_onstring (date) or nullLast date a visit may fall on.
season_from_monthinteger or null`season_from_month` and `season_to_month` are the first and last month of the part of the year a series runs in, 1 for January to 12 for December, both included. Give both or neither. A season may run over the year end: 11 and 2 is November to February. Dates outside it are skipped; the rhythm is not restarted.
At least 1. At most 12.
season_to_monthinteger or null`season_from_month` and `season_to_month` are the first and last month of the part of the year a series runs in, 1 for January to 12 for December, both included. Give both or neither. A season may run over the year end: 11 and 2 is November to February. Dates outside it are skipped; the rhythm is not restarted.
At least 1. At most 12.
start_timestringrequiredduration_minutesintegerrequiredinstructionsstring or nullmembership_idsarray of string (uuid)
Responses
201A repeating visit.
dataobjectrequiredFields(18)
lock_versionintegerrequiredAt least 0.
created_atstring (date-time)requiredupdated_atstring (date-time)requiredidstring (uuid)requiredaccount_idstring (uuid)requiredjob_idstring (uuid)requiredintervalintegerrequiredAt least 1. At most 99.
unitstringrequired`weekday` is Monday to Friday, one visit per working day, and needs an interval of 1.
One of: day, weekday, week, month.
starts_onstring (date)requiredends_onstring (date) or nullseason_from_monthinteger or null`season_from_month` and `season_to_month` are the first and last month of the part of the year a series runs in, 1 for January to 12 for December, both included. Give both or neither. A season may run over the year end: 11 and 2 is November to February. Dates outside it are skipped; the rhythm is not restarted.
At least 1. At most 12.
season_to_monthinteger or null`season_from_month` and `season_to_month` are the first and last month of the part of the year a series runs in, 1 for January to 12 for December, both included. Give both or neither. A season may run over the year end: 11 and 2 is November to February. Dates outside it are skipped; the rhythm is not restarted.
At least 1. At most 12.
start_timestringrequiredduration_minutesintegerrequiredtime_zonestringrequiredinstructionsstring or nullmembership_idsarray of string (uuid)requiredgenerated_throughstring (date) or nullVisits exist up to this date.
A refusal answers in the one error shape every operation shares.
Example
A request our own tests send. The ids are made up: put your own in their place.
curl -X POST "https://app.tradesender.co.uk/api/v1/jobs/4088bebb-3a71-586f-922c-1612b3fa6557/visit_series" \
-H "Authorization: Bearer $TRADESENDER_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"visit_series": {
"interval": 1,
"unit": "week",
"starts_on": "2026-10-19",
"start_time": "09:00",
"duration_minutes": 90,
"instructions": "Weekly lawn cut.",
"membership_ids": [
"379274bb-b710-5b2f-a775-bf99cae8e0ea"
]
}
}'