How to create Custom (Structured) Content in Arc XP
You can create structured content schemas programmatically using the Arc XP Draft API. Schema creation is the only action that is required to be taken via API. After a schema is created, it can be modified to add additional fields from the Data Center UI.
See Structured (Custom) Content in Arc XP to learn more about Structured Content.
This guide walks through a complete schema creation request using POST /draft/v1/schema-type, with a working events schema as the example.
Before you start
You need:
- A valid Arc XP API token with write access to the Draft API
- Your organization’s Arc XP API base URL (i.e.,
https://api.myorg.arcpublishing.com) - A clear picture of your schema structure: field names, types, and which fields need search indexing
That last point is the most important one to get right before sending your first request.
Plan your schema
Two decisions are hard to reverse: field types and search indexing. Both need to be right when you create the schema.
Field types are permanent once records exist. A field defined as short-text cannot become date-time. If you get this wrong and already have data, you’d need to delete all records before fixing the schema, or start with a new one.
Search indexing is configured with the search_settings object on a field. It has two independent dimensions, and both are set through the Draft API:
retrievalmakes the field queryable via the Arc XP Content API (reader-facing query/filter).editorialmakes the field searchable/filterable inside editorial tools (Data Center / Data Manager).
Each dimension is optional, and each takes exactly one index kind. A field with no search_settings is stored but not indexed for search.
Decide both for every field upfront. Think through which fields editors or developers will want to filter or search on, not just which ones need to be stored.
A schema can have up to 200 fields. The other limit that matters is how many fields you make searchable (indexed): that capacity is a pool shared across all schemas in your org, not a per-schema allowance.
Make the request
Endpoint
POST /draft/v1/schema-typeAuthentication uses a Bearer token in the Authorization header.
Request body
A schema requires name, display_name, and fields. The name is the unique machine-readable identifier: 3–30 characters, kebab-case (^[a-z0-9]+(-[a-z0-9]+)*$, e.g. calendar-event or staff-profile). It cannot be changed after creation. display_name is required (1–50 characters); description is optional (up to 500 characters).
A schema must have between 1 and 200 fields, and field keys must be unique within the schema. Each field requires key, type, and display_name — key is kebab- or snake-case (e.g. event_date), and display_name is 1–50 characters. Everything else is optional but worth including.
Field types:
| Type | Use for |
|---|---|
short-text | Titles, labels, short strings |
long-text | Descriptions, body copy |
date-time | Dates and timestamps (ISO 8601) |
geo-point | Location coordinates (lat/lng) |
Additional field types are supported, including boolean, integer, decimal, date, and enum. The valid search index kinds depend on the field type (see below).
Search indexing (search_settings):
Search indexing is set with the search_settings object. It has two optional keys — editorial and retrieval — each an array containing exactly one index kind:
"search_settings": { "editorial": ["keyword"], "retrieval": ["keyword"]}The valid index kinds depend on the field type and on the dimension (editorial vs retrieval):
| Field type | editorial kinds | retrieval kinds |
|---|---|---|
short-text | keyword, semantic | keyword |
long-text | semantic | — |
date-time | range | range |
geo-point | geo | geo |
(For the other field types: boolean and enum support keyword; integer, decimal, and date support range.)
The available index kinds are:
keyword— exact-match filtering and facetingsemantic— embedding/semantic searchrange— numeric and date range queriesgeo— geo-distance queries
Which kinds you can use on a field depends on its type and on whether you’re indexing it for editorial or retrieval (see the table above).
cURL example
This creates an events schema with four fields: a required title indexed for keyword search (both editorial and retrieval), an optional description, a required date, and an optional location.
curl -X POST "https://api.{YOUR_ORG}.arcpublishing.com/draft/v1/schema-type" \ -H "Authorization: Bearer {YOUR_API_TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "name": "calendar-event", "display_name": "Calendar Event", "description": "Schema for event listings such as concerts, conferences, and local happenings.", "fields": [ { "key": "title", "display_name": "Event Title", "description": "Name of the event", "type": "short-text", "is_required": true, "search_settings": { "editorial": ["keyword"], "retrieval": ["keyword"] } }, { "key": "description", "display_name": "Description", "description": "Full event description visible to readers", "type": "long-text", "is_required": false }, { "key": "event_date", "display_name": "Event Date", "description": "Start date and time of the event", "type": "date-time", "is_required": true }, { "key": "venue_location", "display_name": "Venue Location", "description": "Coordinates of the event venue", "type": "geo-point", "is_required": false } ] }'Replace {YOUR_ORG} with your organization identifier and {YOUR_API_TOKEN} with a valid token.
Understand the response
A successful request returns 200 OK with the full schema object:
{ "name": "calendar-event", "display_name": "Calendar Event", "description": "Schema for event listings such as concerts, conferences, and local happenings.", "schema_version": 1, "created_at": "2026-06-26T12:00:00.000Z", "updated_at": "2026-06-26T12:00:00.000Z", "fields": [ { "key": "title", "display_name": "Event Title", "description": "Name of the event", "type": "short-text", "is_required": true, "search_settings": { "editorial": ["keyword"], "retrieval": ["keyword"] } }, { "key": "description", "display_name": "Description", "description": "Full event description visible to readers", "type": "long-text", "is_required": false }, { "key": "event_date", "display_name": "Event Date", "description": "Start date and time of the event", "type": "date-time", "is_required": true }, { "key": "venue_location", "display_name": "Venue Location", "description": "Coordinates of the event venue", "type": "geo-point", "is_required": false } ]}schema_version starts at 1 and increments with each PATCH update. created_at and updated_at are system-managed and read-only.
Common errors
400: Invalid request Returned for all validation failures, including:
- A required property is missing (
name,display_name,fields, or a field’skey/type/display_name) - A field type is not recognized
- The request contains an unrecognized property (the API rejects unknown fields)
- An index kind is not valid for the field’s type, or more than one index kind is supplied for
editorialorretrieval - The schema has zero fields or more than 200, or two fields share the same
key - A schema with that
namealready exists — schema names are unique per organization (message:duplicate schema name '<name>' already exists) - An org limit is exceeded (maximum number of schema types, or the org-wide indexed-field capacity)
Check the error_message in the response for specifics.
403: Forbidden Structured Content is not enabled for your organization. Contact Arc XP support to enable it.
Verify the schema was created
Fetch the schema by name to confirm it looks right:
curl "https://api.{YOUR_ORG}.arcpublishing.com/draft/v1/schema-type/calendar-event" \ -H "Authorization: Bearer {YOUR_API_TOKEN}"To list all schemas in your org:
curl "https://api.{YOUR_ORG}.arcpublishing.com/draft/v1/schema-type" \ -H "Authorization: Bearer {YOUR_API_TOKEN}"