References REST API
Endpoints for managing episode references. References use a library pattern: each unique reference per show lives once in the library (benecaster_reference_library), and per-episode usage is tracked separately (benecaster_episode_references). The library gives the Outlinks add-on a stable reference_id foreign key for cross-episode click aggregation.
All endpoints require manage_options and a valid X-WP-Nonce header.
Episode Reference Usage
These endpoints manage which library items are attached to a specific episode.
GET /benecaster/v1/episodes/{id}/references
Returns the ordered array of reference usage objects for an episode, joined with library data.
Response:
[
{
"id": 1,
"reference_id": 42,
"label": "Sarah's website",
"url": "https://sarahchen.com",
"description": null,
"display_label": null,
"group_id": null,
"display_order": 0
}
]
Field notes:
| Field | Description |
|---|---|
id |
benecaster_episode_references.id — use this in PUT and DELETE |
reference_id |
benecaster_reference_library.id — stable FK for Outlinks add-on |
label |
Resolved display label: display_label if set, otherwise the library label |
display_label |
Per-episode label override; null = use library label |
url, description |
From the library item |
group_id |
References group assignment; null = ungrouped |
display_order |
Sort position; 0-indexed |
POST /benecaster/v1/episodes/{id}/references
Creates a new reference usage on the episode. Either link an existing library item by reference_id, or provide a label to find-or-create one.
Body:
{
"reference_id": 42,
"label": "Sarah's website",
"url": "https://sarahchen.com",
"description": null,
"display_label": null,
"group_id": null,
"display_order": 0
}
Body field notes:
| Field | Notes |
|---|---|
reference_id |
Optional. If provided, skips library lookup. Returns 404 if the library item doesn’t exist on this show. |
label |
Required if reference_id absent. Used to find-or-create a library item matched by (show_id, label). |
url, description |
Used only when creating a new library item; ignored if item already exists. |
display_label, group_id, display_order |
Optional; default null/null/0. |
Response: 201 Created — reference usage object (same shape as GET).
PUT /benecaster/v1/episodes/{id}/references/{ref_id}
Updates a reference usage on the episode. {ref_id} is benecaster_episode_references.id. All fields optional.
To update the underlying library item (label, url, description) for all episodes at once, use PUT /shows/{show_id}/reference-library/{lib_id} instead.
Body:
{
"display_label": "Sarah's book site",
"group_id": 7,
"display_order": 1
}
Response: Updated reference usage object.
Errors:
| Code | HTTP | Condition |
|---|---|---|
rest_not_found |
404 | ref_id does not exist on this episode |
DELETE /benecaster/v1/episodes/{id}/references/{ref_id}
Removes a reference usage from the episode. The library item is retained — other episodes citing it are unaffected.
Response: 204 No Content
Show-Level Reference Library
The library holds one record per unique reference per show.
GET /benecaster/v1/shows/{id}/reference-library
Returns all library items for a show.
Response:
[
{ "id": 42, "label": "Sarah's website", "url": "https://sarahchen.com", "description": null }
]
POST /benecaster/v1/shows/{id}/reference-library
Creates a library item explicitly. In normal episode-save flow, items are created implicitly — use this endpoint when the UI needs to pre-populate the library before attaching to an episode.
Body:
{
"label": "The Lean Startup",
"url": "https://theleanstartup.com",
"description": null
}
url and description are optional.
Response: 201 Created with the library item object.
GET /benecaster/v1/shows/{id}/reference-library/search
Searches library items by label or URL substring — powers the episode editor typeahead.
Parameters:
| Param | Type | Default | Description |
|---|---|---|---|
q |
string | — | Search term (matches label or URL substring) |
per_page |
int | 20 | Max results |
Response:
[
{ "id": 42, "label": "The Lean Startup", "url": "https://theleanstartup.com", "description": null }
]
Selecting a result pre-fills reference_id, label, url, and description in the reference entry form without creating a new library item.
PUT /benecaster/v1/shows/{id}/reference-library/{lib_id}
Updates a library item. Changes apply to the resolved label, url, and description for all episodes that cite this item (unless overridden per-episode by display_label).
Body:
{
"label": "The Lean Startup",
"url": "https://updated-url.com",
"description": "Classic startup methodology book"
}
All fields optional.
Response: Updated library item object.
DELETE /benecaster/v1/shows/{id}/reference-library/{lib_id}
Deletes a library item and all benecaster_episode_references rows that reference it. This affects every episode that cited this reference — the reference disappears from all of them simultaneously.
Response: 204 No Content
Reference Groups
Groups let you organize references under named headings within the episode references section.
GET /benecaster/v1/shows/{id}/reference-groups
Returns the ordered array of reference group definitions for a show.
Response:
[
{ "id": 7, "name": "Books", "display_order": 0 },
{ "id": 8, "name": "Tools", "display_order": 1 }
]
POST /benecaster/v1/shows/{id}/reference-groups
Creates a new reference group for a show.
Body:
{
"name": "Books",
"display_order": 0
}
display_order is optional (defaults to 0).
Response: 201 Created with the created group object.
PUT /benecaster/v1/shows/{id}/reference-groups/{group_id}
Updates a reference group’s name or display order. All fields optional.
Body:
{
"name": "Books & Articles",
"display_order": 0
}
Response: Updated group object.
Errors:
| Code | HTTP | Condition |
|---|---|---|
rest_not_found |
404 | group_id does not exist on this show |
DELETE /benecaster/v1/shows/{id}/reference-groups/{group_id}
Deletes a reference group. All benecaster_episode_references rows that use this group_id become ungrouped (group_id SET NULL) — no reference data is lost, and references appear at the end of the list under no heading.
Response: 204 No Content
Filter
benecaster_episode_references fires in the REST response for GET /episodes/{id}/references and for episode objects that embed references. Use this filter to inject synthetic references from an add-on or to reorder/annotate the existing array.
See Recipe: Annotate Episode References with Tracked Redirect URLs.