DevelopersREST API
Content API
List content library entries, see where an entry has been used across projects, and assign tags to many entries at once with the AutoRFP.ai REST API.
Content is your approved content library. Use these endpoints to list entries, see where an entry has been used across projects, and add, remove or replace tags on many entries at once.
Reading content needs the content:read scope. Assigning tags needs content:write, which is a write scope.
List content#
get/v1/content
Returns a paginated list of content library entries accessible via the API key.
Required scopecontent:read
Query parameters
page[number]integerPage number (1-indexed)
page[size]integerItems per page (1-100)
filter[tag]stringTag label to filter by
filter[updatedAfter]string (date-time)ISO 8601 datetime (e.g. "2025-01-01T00:00:00Z")
filter[updatedBefore]string (date-time)ISO 8601 datetime (e.g. "2025-01-01T00:00:00Z")
Returns
Paginated list of content
typeenumrequiredidstringrequiredattributesobjectrequiredShow child attributes
titlestring | nullrequiredContent title, question text for QA, section heading for documentation
tagsarray of objectsrequiredAssigned tags: id plus resolved label (label null when the id is not in the current tag vocabulary, an orphan)
Show child attributes
idstringrequiredlabelstring | nullrequired
teamOwnerIdsarray of stringsrequiredIDs of teams that own this content
createdAtstring | nullrequiredISO 8601 datetime when the content was created
updatedAtstring | nullrequiredISO 8601 datetime when the content was last updated
reviewedAtstring | nullrequiredISO 8601 datetime when the content was last reviewed
projectUsageCountnumberrequiredNumber of distinct non-deleted projects that currently reference this content. Live reverse-lookup, not the stored monotonic usageProjectCount.
metaobjectrequiredShow child attributes
pageobjectrequiredShow child attributes
numbernumberrequiredsizenumberrequiredtotalItemsnumberrequiredtotalPagesnumberrequired
linksobjectrequiredShow child attributes
selfstringrequiredfirststringrequiredlaststring | nullrequiredprevstring | nullrequirednextstring | nullrequired
Errors
| Status | Meaning |
|---|---|
400 | Invalid query parameters |
401 | Unauthorized |
403 | Insufficient permissions |
429 | Rate limit exceeded |
500 | Internal server error |
Request
curl -g "https://api.autorfp.ai/v1/content?page[size]=25" \
-H "Authorization: Bearer $AUTORFP_API_KEY"const response = await fetch("https://api.autorfp.ai/v1/content?page[size]=25", {
headers: {
Authorization: `Bearer ${process.env.AUTORFP_API_KEY}`,
},
});
const data = await response.json();
console.log(data);import os
import requests
response = requests.get(
"https://api.autorfp.ai/v1/content",
headers={"Authorization": "Bearer " + os.environ["AUTORFP_API_KEY"]},
params={"page[size]": 25},
)
print(response.json())Response
Response
{
"data": [
{
"type": "content",
"id": "8f14e45f",
"attributes": {
"title": "example",
"tags": [
{
"id": "8f14e45f",
"label": "Security"
}
],
"teamOwnerIds": [
"8f14e45f"
],
"createdAt": "2026-03-02T09:30:00.000Z",
"updatedAt": "2026-03-02T09:30:00.000Z",
"reviewedAt": "2026-03-02T09:30:00.000Z",
"projectUsageCount": 1
}
}
],
"meta": {
"page": {
"number": 1,
"size": 1,
"totalItems": 1,
"totalPages": 1
}
},
"links": {
"self": "https://api.autorfp.ai/v1/content?page[number]=1&page[size]=25",
"first": "https://api.autorfp.ai/v1/content?page[number]=1&page[size]=25",
"last": "https://api.autorfp.ai/v1/content?page[number]=1&page[size]=25",
"prev": "https://api.autorfp.ai/v1/content?page[number]=1&page[size]=25",
"next": "https://api.autorfp.ai/v1/content?page[number]=2&page[size]=25"
}
}List content usage#
get/v1/content/{id}/usage
Returns a paginated list of usage records showing where a content library entry has been used across projects.
Required scopecontent:read
Path parameters
idstringrequired
Query parameters
page[number]integerPage number (1-indexed)
page[size]integerItems per page (1-100)
Returns
Paginated list of content usage records
typeenumrequiredidstringrequiredResponse ID
attributesobjectrequiredShow child attributes
projectIdstringrequiredID of the project where the content was used
requirementIdstringrequiredID of the requirement (response ID)
usageTypeenumrequiredHow the content was used. 'verbatim' = the response engine used this content as the direct answer source. 'ai_generation' = the response engine used this content as supporting context. 'user_added' = a user explicitly inserted this content into the response while editing.
metaobjectrequiredShow child attributes
pageobjectrequiredShow child attributes
numbernumberrequiredsizenumberrequiredtotalItemsnumberrequiredtotalPagesnumberrequired
linksobjectrequiredShow child attributes
selfstringrequiredfirststringrequiredlaststring | nullrequiredprevstring | nullrequirednextstring | nullrequired
Errors
| Status | Meaning |
|---|---|
400 | Invalid query parameters |
401 | Unauthorized |
403 | Insufficient permissions |
404 | Content not found |
429 | Rate limit exceeded |
500 | Internal server error |
Request
curl -g "https://api.autorfp.ai/v1/content/8f14e45f/usage?page[size]=25" \
-H "Authorization: Bearer $AUTORFP_API_KEY"const response = await fetch("https://api.autorfp.ai/v1/content/8f14e45f/usage?page[size]=25", {
headers: {
Authorization: `Bearer ${process.env.AUTORFP_API_KEY}`,
},
});
const data = await response.json();
console.log(data);import os
import requests
response = requests.get(
"https://api.autorfp.ai/v1/content/8f14e45f/usage",
headers={"Authorization": "Bearer " + os.environ["AUTORFP_API_KEY"]},
params={"page[size]": 25},
)
print(response.json())Response
Response
{
"data": [
{
"type": "content-usage",
"id": "8f14e45f",
"attributes": {
"projectId": "8f14e45f",
"requirementId": "8f14e45f",
"usageType": "verbatim"
}
}
],
"meta": {
"page": {
"number": 1,
"size": 1,
"totalItems": 1,
"totalPages": 1
}
},
"links": {
"self": "https://api.autorfp.ai/v1/content/8f14e45f/usage?page[number]=1&page[size]=25",
"first": "https://api.autorfp.ai/v1/content/8f14e45f/usage?page[number]=1&page[size]=25",
"last": "https://api.autorfp.ai/v1/content/8f14e45f/usage?page[number]=1&page[size]=25",
"prev": "https://api.autorfp.ai/v1/content/8f14e45f/usage?page[number]=1&page[size]=25",
"next": "https://api.autorfp.ai/v1/content/8f14e45f/usage?page[number]=2&page[size]=25"
}
}Bulk assign tags to content#
post/v1/content/tags
Adds, removes, or replaces tags across up to 500 content library items. Requires content:write. Well-formed batches always return 200 with per-item outcomes in successfulContentIds and failures[].
Required scopecontent:write
Request body
typeenumrequiredHow to apply the tags: 'add', 'remove', or 'replace'.
itemsarray of objectsrequiredContent items to update (max 500 per request, unique contentId per item)
Show child attributes
contentIdstringrequiredContent embedding id to tag (max 128 chars)
tagIdsarray of stringsrequiredTag ids to add/remove/replace on the item (max 100, each max 128 chars)
Returns
Bulk tag assignment result (partial success possible)
typeenumrequiredidstringrequiredServer-generated batch result id (not a content or tag id)
attributesobjectrequiredShow child attributes
typeenumrequiredThe operation type from the request
countsobjectrequiredShow child attributes
totalItemsnumberrequiredNumber of items in the request
successfulItemsnumberrequiredNumber of items whose tags were updated
unsuccessfulItemsnumberrequiredNumber of items that were not updated
successfulContentIdsarray of stringsrequiredContent ids whose tags were updated
failuresarray of objectsrequiredPer-item outcomes that need attention. A contentId may appear here as tag-not-found while still being in successfulContentIds (valid tags were applied). content-not-found / no-edit-access mean the item was not updated. write-failed means the update did not fully succeed and may be partially applied (e.g. stored but the search index not yet updated); the operations are idempotent, so re-issue the same request to converge. tagIds is set for tag-not-found.
Show child attributes
contentIdstringrequiredcodeenumrequiredtagIdsarray of strings
Errors
| Status | Meaning |
|---|---|
400 | Malformed body, caps exceeded, or duplicate contentId |
401 | Unauthorized |
403 | Insufficient scope |
429 | Rate limit exceeded |
500 | Internal server error |
Request
curl -g -X POST "https://api.autorfp.ai/v1/content/tags" \
-H "Authorization: Bearer $AUTORFP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "add",
"items": [
{
"contentId": "8f14e45f",
"tagIds": [
"8f14e45f"
]
}
]
}'const response = await fetch("https://api.autorfp.ai/v1/content/tags", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.AUTORFP_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"type": "add",
"items": [
{
"contentId": "8f14e45f",
"tagIds": [
"8f14e45f"
]
}
]
}),
});
const data = await response.json();
console.log(data);import os
import requests
response = requests.post(
"https://api.autorfp.ai/v1/content/tags",
headers={"Authorization": "Bearer " + os.environ["AUTORFP_API_KEY"]},
json={
"type": "add",
"items": [
{
"contentId": "8f14e45f",
"tagIds": [
"8f14e45f",
],
},
],
},
)
print(response.json())Response
Response
{
"data": {
"type": "content-tag-assignment-result",
"id": "8f14e45f",
"attributes": {
"type": "add",
"counts": {
"totalItems": 1,
"successfulItems": 1,
"unsuccessfulItems": 1
},
"successfulContentIds": [
"8f14e45f"
],
"failures": [
{
"contentId": "8f14e45f",
"code": "content-not-found",
"tagIds": [
"8f14e45f"
]
}
]
}
}
}