Endpoints
Use the plan slots endpoints to manage recurring posting slots and batch-assign draft posts to the next eligible slot occurrence. The slot response shape is documented on the Plan slot object page.
GET /plan/slots
List plan slots owned by the authenticated caller.
Query parameters
| Field | Type | Description |
|---|---|---|
| limit | number | Page size. Defaults to 20 and cannot exceed 100. |
| cursor | string | Opaque pagination cursor returned by a previous response. |
Example request
curl --request GET \
--url 'https://api.feedhive.com/plan/slots?limit=20' \
--header 'accept: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY'Response body
| Field | Type | Description |
|---|---|---|
| success | boolean | Whether the request succeeded. |
| data.items | Plan slot[] | Returned plan slots for this page. |
| data.total | number | Total number of plan slots owned by the caller. |
| data.has_more | boolean | Whether another page of slots is available. |
| data.next_cursor | string | null | Cursor for the next page, or null when there are no more results. |
Error responses
| Status | Message | Reason |
|---|---|---|
400 | "Invalid limit parameter" | limit is not a valid positive integer. |
400 | "Invalid cursor" | cursor cannot be decoded. |
GET /plan/slots/:id
Fetch a single plan slot by ID.
Path parameters
| Field | Type | Description |
|---|---|---|
| id | string | Slot identifier. |
Example request
curl --request GET \
--url https://api.feedhive.com/plan/slots/slot_123 \
--header 'accept: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY'Response body
| Field | Type | Description |
|---|---|---|
| success | boolean | Whether the request succeeded. |
| data | Plan slot | Requested plan slot. |
Error responses
| Status | Message | Reason |
|---|---|---|
400 | "Missing slot ID" | No slot ID was provided in the request path. |
404 | "Slot not found" | No slot exists with the given ID. |
403 | "Access denied" | The slot exists but belongs to a different owner. |
POST /plan/slots
Create a plan slot owned by the authenticated caller.
Request body
| Field | Type | Description |
|---|---|---|
| week_day | integer | Required. Day of the week where 0 is Sunday and 6 is Saturday. |
| start_time | string | Required. Recurring local start time in HH:MM 24-hour format. |
| end_time | string | Required. Recurring local end time in HH:MM 24-hour format. Must be later than start_time on the same day. |
| timezone | string | Optional IANA timezone used to interpret start_time and end_time. Falls back to owner settings and then UTC. |
| label_ids | string[] | Optional array of unique label IDs owned by the same caller. |
| recurrence | Recurrence | Required recurrence object. |
| is_active | boolean | Optional active flag. Defaults to true when omitted. |
Recurrence
| Field | Type | Description |
|---|---|---|
| interval | daily | weekly | monthly | Required recurrence interval. |
| repeat_every | integer | Required repeat frequency. Must be greater than or equal to 1. |
Example request
curl --request POST \
--url https://api.feedhive.com/plan/slots \
--header 'accept: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"week_day": 1,
"start_time": "13:30",
"end_time": "14:30",
"timezone": "Europe/Copenhagen",
"label_ids": ["lbl_1", "lbl_2"],
"recurrence": {
"interval": "weekly",
"repeat_every": 1
},
"is_active": true
}'Response body
| Field | Type | Description |
|---|---|---|
| success | boolean | Whether the request succeeded. |
| data | Plan slot | Created plan slot. |
Validation errors
| Message | Reason |
|---|---|
"week_day is required" | Field missing. |
"week_day must be an integer between 0 and 6" | Invalid day of week. |
"start_time is required" | Field missing. |
"start_time must be in HH:MM 24-hour format" | Invalid time format. |
"end_time is required" | Field missing. |
"end_time must be in HH:MM 24-hour format" | Invalid time format. |
"end_time must be later than start_time on the same day" | Invalid time range. |
"timezone must be a valid IANA timezone" | Timezone string is not recognized. |
"recurrence is required" | Field missing. |
"recurrence.interval must be one of: daily, weekly, monthly" | Invalid recurrence interval. |
"recurrence.repeat_every must be an integer greater than or equal to 1" | Invalid repeat frequency. |
"label_ids must be an array of unique label IDs" | Invalid or duplicate label IDs. |
"One or more labels were not found" | Referenced label does not exist. |
"Access denied" | A referenced label belongs to a different owner. |
PATCH /plan/slots/:id
Update a plan slot. Only the fields you send are updated.
If timezone is omitted, the existing slot timezone is preserved. If you send only timezone, the slot keeps the same local clock times and the underlying UTC values are re-derived for the new timezone.
Path parameters
| Field | Type | Description |
|---|---|---|
| id | string | Slot identifier. |
Request body
| Field | Type | Description |
|---|---|---|
| week_day | integer | Optional day of the week where 0 is Sunday and 6 is Saturday. |
| start_time | string | Optional local start time in HH:MM 24-hour format. |
| end_time | string | Optional local end time in HH:MM 24-hour format. Must be later than the effective start_time. |
| timezone | string | Optional IANA timezone. When provided, the slot timezone is updated durably. |
| label_ids | string[] | Optional replacement array of unique label IDs. Replaces all slot labels. |
| recurrence | Recurrence | Optional replacement recurrence object. |
| is_active | boolean | Optional active flag. |
Example request
curl --request PATCH \
--url https://api.feedhive.com/plan/slots/slot_123 \
--header 'accept: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"week_day": 2,
"start_time": "15:00",
"end_time": "16:00",
"timezone": "Europe/Copenhagen",
"label_ids": ["lbl_3"],
"recurrence": {
"interval": "daily",
"repeat_every": 1
},
"is_active": false
}'Response body
| Field | Type | Description |
|---|---|---|
| success | boolean | Whether the request succeeded. |
| data | Plan slot | Updated plan slot. |
Error responses
| Status | Message | Reason |
|---|---|---|
400 | "Missing slot ID" | No slot ID was provided in the request path. |
400 | "No valid fields provided for update" | The request body contained no writable fields. |
400 | "week_day must be an integer between 0 and 6" | Invalid day of week. |
400 | "start_time must be in HH:MM 24-hour format" | Invalid time format. |
400 | "end_time must be in HH:MM 24-hour format" | Invalid time format. |
400 | "end_time must be later than start_time on the same day" | Invalid time range. |
400 | "timezone must be a valid IANA timezone" | Timezone string is not recognized. |
400 | "recurrence.interval must be one of: daily, weekly, monthly" | Invalid recurrence interval. |
400 | "recurrence.repeat_every must be an integer greater than or equal to 1" | Invalid repeat frequency. |
400 | "label_ids must be an array of unique label IDs" | Invalid or duplicate label IDs. |
400 | "One or more labels were not found" | Referenced label does not exist. |
403 | "Access denied" | Slot or label belongs to a different owner. |
404 | "Slot not found" | No slot exists with the given ID. |
DELETE /plan/slots/:id
Delete a plan slot. This removes the slot definition only and does not automatically change posts already assigned to future occurrences.
Path parameters
| Field | Type | Description |
|---|---|---|
| id | string | Slot identifier. |
Example request
curl --request DELETE \
--url https://api.feedhive.com/plan/slots/slot_123 \
--header 'accept: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY'Response body
| Field | Type | Description |
|---|---|---|
| success | boolean | Whether the request succeeded. |
| data | Plan slot | Deleted plan slot. |
Error responses
| Status | Message | Reason |
|---|---|---|
400 | "Missing slot ID" | No slot ID was provided in the request path. |
404 | "Slot not found" | No slot exists with the given ID. |
403 | "Access denied" | The slot exists but belongs to a different owner. |
POST /plan/assign-next
Batch-assign one or more draft posts to the next eligible slot occurrence.
This endpoint returns 200 OK whenever the request shape is valid, even if some posts fail to assign. Check the items array for per-post success or failure details. Successful items return the Post object.
Assignment behavior
- Posts are processed in request order.
- If a post has no labels, only slots with no labels are eligible.
- If a post has one or more labels, a slot must share at least one label ID.
- Inactive slots are always excluded.
- Earlier successful assignments in the same request make their chosen occurrences unavailable to later posts.
Exact time vs random time
- If the owner or workspace setting
exactSlotTimesis enabled, the post is scheduled at the slot occurrence start time. - If
exactSlotTimesis disabled, the post is scheduled at a uniformly random instant inside the occurrence time range.
Occupancy definition
A slot occurrence is considered occupied when another post already exists with:
- the same
slot_id - a status equivalent to scheduled or pending approval
- a
scheduled_atvalue that falls within that occurrence time range
Request body
| Field | Type | Description |
|---|---|---|
| post_ids | string[] | Required. Non-empty array of unique draft post IDs to assign. |
Example request
curl --request POST \
--url https://api.feedhive.com/plan/assign-next \
--header 'accept: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"post_ids": ["post_1", "post_2", "post_3"]
}'Response body
| Field | Type | Description |
|---|---|---|
| success | boolean | Whether the request shape was valid. |
| data.items | AssignmentResult[] | Per-post assignment results in request order. |
AssignmentResult
| Field | Type | Description |
|---|---|---|
| post_id | string | Original post ID from the request. |
| success | boolean | Whether assignment succeeded for that post. |
| data | Post | null | Updated Post object when success is true. |
| message | string | null | Failure reason when success is false. |
Request validation errors
| Message | Reason |
|---|---|
"Request body must be a JSON object" | The request body is not a JSON object. |
"post_ids is required" | Field missing from the request body. |
"post_ids must be an array" | Field is not an array. |
"post_ids must not be empty" | Array is empty. |
"Each post ID must be a string" | One or more values are not strings. |
"Duplicate post ID \"<id>\"" | The same post ID was sent more than once. |
Per-item failure messages
| Message | Reason |
|---|---|
"Post not found" | No post exists with the given ID, or it has been deleted. |
"Access denied" | The post exists but belongs to a different owner. |
"Post is already scheduled" | The post already has scheduled status. |
"Only draft posts can be assigned" | The post is not a draft. |
"Post must have at least one social account" | The post has no connected social accounts. |
"No available slot" | No active matching slot has an unoccupied future occurrence. |