Your First API Call
Make your first Nomad Media API call with a working code example.
Your First API Call
This page walks through the fundamental patterns you'll use in every Nomad Media integration: listing records, reading a single record, creating a record, updating, and searching. All examples use the Admin API — see Quick Start for authentication and setup.
The Core Pattern
Every content API call requires three things:
- A bearer token from the login endpoint, passed as
Authorization: Bearer <token> - A Content Definition ID — the UUID that identifies which content type you are working with (e.g. the "Meeting" or "Committee" schema). Think of this as the table name.
- A Content Record ID (for single-record operations) — the UUID of the specific record
Data is passed and returned as a property bag: a flat JSON object where each key is the propertyName configured for that field in the Site Manager. For relationship fields, the value is the UUID of the related record.
How to find your Content Definition ID In the Admin UI, navigate to Site Manager and select your content definition. The ID appears in the URL or in the definition's detail panel. You can also retrieve all content definitions via
GET /admin/content-definitions.
List Records
GET /admin/content/{contentDefinitionId}?pageSize=25&pageOffset=0
Authorization: Bearer <token>
JavaScript:
const response = await fetch(
`${apiUrl}/admin/content/${contentDefinitionId}?pageSize=25&pageOffset=0`,
{ headers: { Authorization: `Bearer ${token}` } }
);
const { items, totalItemCount } = await response.json();Python:
import requests
response = requests.get(
f"{api_url}/admin/content/{content_definition_id}",
params={"pageSize": 25, "pageOffset": 0},
headers={"Authorization": f"Bearer {token}"}
)
data = response.json()
items = data["items"]Get a Single Record
GET /admin/content/{contentDefinitionId}/{recordId}
Authorization: Bearer <token>
JavaScript:
const response = await fetch(
`${apiUrl}/admin/content/${contentDefinitionId}/${recordId}`,
{ headers: { Authorization: `Bearer ${token}` } }
);
const record = await response.json();Python:
response = requests.get(
f"{api_url}/admin/content/{content_definition_id}/{record_id}",
headers={"Authorization": f"Bearer {token}"}
)
record = response.json()Create a Record
Pass a property bag in the request body. Keys must exactly match the propertyName values configured in the content definition. For relationship fields (related content definition, multi-select, asset selector), pass the UUID of the related record — not a string label.
POST /admin/content/{contentDefinitionId}
Authorization: Bearer <token>
Content-Type: application/json
{
"title": "Finance Committee",
"committeeCode": "FIN",
"chamberId": "a1b2c3d4-0000-0000-0000-000000000000"
}
chamberIdis a relationship field — its value is the UUID of the related Chamber record, not the chamber's name.
JavaScript:
const response = await fetch(
`${apiUrl}/admin/content/${contentDefinitionId}`,
{
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
title: "Finance Committee",
committeeCode: "FIN",
chamberId: "a1b2c3d4-0000-0000-0000-000000000000"
})
}
);
const newRecord = await response.json();
const newRecordId = newRecord.contentId; // store this UUID for future updatesPython:
response = requests.post(
f"{api_url}/admin/content/{content_definition_id}",
headers={
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
},
json={
"title": "Finance Committee",
"committeeCode": "FIN",
"chamberId": "a1b2c3d4-0000-0000-0000-000000000000"
}
)
new_record = response.json()
new_record_id = new_record["contentId"]Update a Record
PUT /admin/content/{contentDefinitionId}/{recordId}
Authorization: Bearer <token>
Content-Type: application/json
{
"title": "Updated Committee Name"
}
Only the fields included in the request body are updated — omitted fields retain their existing values.
Delete a Record
DELETE /admin/content/{contentDefinitionId}/{recordId}
Authorization: Bearer <token>
Search
The Search API queries across all content definitions simultaneously. Use filters to scope results to a specific content type or field value. The fieldName values in filters must exactly match the propertyName of the field as configured in the Site Manager.
POST /admin/search
Authorization: Bearer <token>
Content-Type: application/json
{
"filters": [
{ "fieldName": "contentDefinitionId", "value": "<your-content-def-id>" },
{ "fieldName": "externalId", "value": "12345" }
],
"sortFields": [{ "fieldName": "title", "sortOrder": "ASC" }],
"pageSize": 25,
"pageOffset": 0
}
JavaScript:
const response = await fetch(`${apiUrl}/admin/search`, {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
filters: [
{ fieldName: "contentDefinitionId", value: contentDefinitionId },
{ fieldName: "externalId", value: "12345" }
],
sortFields: [{ fieldName: "title", sortOrder: "ASC" }],
pageSize: 25,
pageOffset: 0
})
});
const { items, totalItemCount } = await response.json();Tip: Use
GET /admin/search/mappingFieldNamesto retrieve all indexed field names available for use in filters and sort fields.
Next Steps
- Key Concepts — content definitions, field types, and the full data model
- Search API Reference — full search endpoint reference
- Data Synchronization — recommended pattern for syncing records from an external system
- SDKs — use an SDK to handle auth, token refresh, and keep-alives automatically
