1. Search experiences

Ingestion Service API

IMPORTANT

Feature availability is part of a phased rollout. Your organization may not see this functionality yet. It will become available when your environment is included in the rollout.

The Ingestion Service API lets you submit documents directly to a search source for indexing. You can use it with push sources, site sources, and content sources. Submitted content can be returned by search experiences that use the source, including search results, autocomplete suggestions, and recommendation experiences.

Supported source types

The source type determines how you identify a document:

Source typeRequired identityURL behavior
Push sourceidsc_url is optional. Supply it when search results need a clickable URL.
Site sourcesc_urlThe URL identifies the document and must match the crawled URL exactly.
Content sourceidsc_url is optional. Supply it when search results need a clickable URL.

Use a push source when an external system is the system of record or when the content cannot be crawled. You can use the API to make targeted updates to site and content sources, but those updates are temporary.

Warning

A crawl or content re-index builds a new index and replaces the previous index. Pushed additions, updates, and deletions in a site or content source can disappear when that process completes. If a pushed change must persist, replay it after the crawl or re-index. Use a push source when the external system must remain the source of truth.

Before you start

Before you send documents, make sure that:

  • The source exists and is published.
  • The fields you send are already defined in the source schema. The API does not create fields.
  • You know the source config_id.
  • You have a Push API key. Keys are instance-wide and can send documents to any source in the SCAI instance.

The API writes to the live index. It does not provide a dry run, preview, or separate publish step.

Authentication

All Ingestion Service API requests require a static API key in the Authorization header:

Authorization: ApiKey <your-api-key>

Create an API key

In production environments, you must authenticate using a static API key. You can create API keys from the Profile import page in SitecoreAI settings.

Note

In production environments, only Organization Owners and Organization Admins can create API keys. In non-production environments, all users can create API keys.

To create an API key:

  1. In SitecoreAI, click Content > Search Sources > Settings.
  2. Click Create credential.
  3. Enter a name for the credential and an optional description.
  4. Click Create, then copy the API key. The key is displayed only one time and cannot be retrieved after you close the dialog.
Warning

Copy the API key before closing the dialog. You cannot retrieve it again after it disappears. If you lose it, you must create a new credential.

Base URL

To find your base URL, open SitecoreAI and navigate to the source configuration. Use the API Endpoint value shown for the source.

Use the API Endpoint value as {base_url} in API requests.

The complete request URL follows this pattern:

{base_url}/v1/index/{config_id}/push

Endpoints

Note

The Ingestion Service API uses only one endpoint, operations are pushed to the index using the operations object.

MethodPathDescription
POST/v1/index/{config_id}/pushSubmit document operations to create, update, or remove documents from a search source.

Push documents to a source

Submits one or more document operations for processing.

Endpoint: POST /v1/index/{config_id}/push

Content type: application/json

Path parameters

ParameterTypeRequiredDescription
config_idStringYesThe identifier of the search source configuration.

Request body

The request body contains one or more document operations.

The request can contain 1 to 50 operations and must not exceed 512 KiB. If either limit is exceeded, the complete request is rejected before any operation is indexed. Split larger loads into multiple requests and control your request concurrency.

Request fields

FieldTypeRequiredDescription
operationsArrayYesThe document operations to execute. Each operation specifies content to add, update, or remove from the search index.
operations[].actionStringYesThe operation to perform on the document. Supported actions include upsert to create or update a document and delete to remove a document from the index.
operations[].sc_urlStringConditionalRequired for every operation on a site source. Optional for a push or content source, where it only sets a clickable URL for search results.
operations[].canonical_urlStringNoFor a site source, an optional URL used together with locale to group language versions of the same page under one canonical document. canonical_url and locale do not replace the required sc_url. Not used for push or content sources.
operations[].localeStringConditionalRequired when the source has locales configured. For example, en-US.
operations[].fieldsObjectConditionalRequired for upsert operations. Each property is a key-value pair whose name must match the source schema. Do not include this property for delete operations.
operations[].fields.<field_name>StringNoThe value of a field to index. Field names and values depend on your document schema and can include content such as titles, descriptions, categories, or custom metadata.
operations[].idStringConditionalRequired for push and content sources. Use the external document identifier or Sitecore item ID.
Important

Use the compact YYYYMMDDTHHMMSSZ format for datetime values. ISO 8601 values such as 2026-07-06T15:04:05Z are not accepted.

Field names are case-sensitive and must already exist in the source schema. Field names beginning with sc_ and @search.action are reserved and are ignored when sent inside fields. The platform sets system fields such as sc_item_id, sc_locale, and sc_url from the operation identity values.

Example request

curl -X POST "{base_url}/v1/index/{config_id}/push" \
  -H "Authorization: ApiKey <your-api-key>" \
  -H "Content-Type: application/json" \
  -d @operations.json

Example request body for a site source

{
  "operations": [
    {
      "action": "upsert",
      "sc_url": "https://www.example.com/products/sku-001",
      "canonical_url": "https://www.example.com/products/sku-001",
      "locale": "en-US",
      "fields": {
        "title": "Example Product",
        "description": "Updated via push API"
      }
    },
    {
      "action": "delete",
      "sc_url": "https://www.example.com/products/sku-999"
    }
  ]
}

Example request body for a push source

{
  "operations": [
    {
      "action": "upsert",
      "id": "sku-10432",
      "locale": "en",
      "fields": {
        "title": "Hydraulic Pump HP-200",
        "price": "1299.50",
        "in_stock": "true"
      }
    }
  ]
}

Example request body for a content source

{
  "operations": [
    {
      "action": "upsert",
      "id": "{A8F2C1D0-3E45-4B77-9C12-0D6E5F8A1B23}",
      "locale": "en",
      "sc_url": "https://www.example.com/autumn-campaign",
      "fields": {
        "title": "Autumn campaign landing page",
        "summary": "Campaign hub for the autumn promotion."
      }
    }
  ]
}

Delete documents

Delete operations do not require fields, only a way to identify the document. This will depend on the type of source you are using:

For a site source, documents are identified by sc_url:

{
  "operations": [
    { "action": "delete", "sc_url": "https://www.example.com/retired-page", "locale": "en" }
  ]
}

For a push or content source, documents are identified by id:

{
  "operations": [
    { "action": "delete", "id": "sku-10432", "locale": "en" }
  ]
}
Note

upsert merges the fields you send into the existing document. Fields that you omit retain their existing values. To clear a field, send an empty string.

Locales

If you have configured locales for your source, locale is required on every operation. Locale variants are stored as separate documents. For a multi-locale site source, use canonical_url to group language variants of the same page, but include sc_url on every operation because canonical_url and locale do not replace it.

Success response

200 OK

All operations were processed successfully.

{
  "results": [
    {
      "action": "upsert",
      "index": 0,
      "key": "https://www.example.com/products/sku-001",
      "statusCode": 200,
      "succeeded": true
    }
  ],
  "status": "success"
}

Partial success response

207 Multi-Status

One or more operations failed while others succeeded.

{
  "results": [
    {
      "action": "upsert",
      "index": 0,
      "key": "https://www.example.com/products/sku-001",
      "statusCode": 200,
      "succeeded": true
    },
    {
      "action": "delete",
      "index": 1,
      "key": "sku-10432",
      "statusCode": 400,
      "succeeded": false,
      "errorMessage": "field \"colour\" is not defined in config"
    }
  ],
  "status": "partial_success"
}

Response fields

FieldDescription
resultsThe result of each operation submitted in the request.
results[].actionThe operation that was processed.
results[].errorMessageDetails about an error that occurred while processing the operation. Empty when the operation succeeds.
results[].indexThe zero-based position of the operation in the request payload.
results[].keyThe identifier of the processed document.
results[].statusCodeThe status code returned for the operation.
results[].succeededIndicates whether the operation completed successfully.
statusThe overall request status.

Treat 207 Multi-Status as a normal response. Use each result's zero-based index to map failures back to the original operations array, and retry only the operations where succeeded is false.

Error responses

StatusCause
400 Bad RequestInvalid request body, empty or oversized operation list, unsupported action, missing identity, invalid field value, or field not defined in the source schema.
401 Unauthorized / 403 ForbiddenThe API key is missing, invalid, expired, revoked, or does not have the search.pushapi:m scope.
404 Not FoundThe specified configuration was not found, is not published, or is not owned by the authenticated instance.
413 Payload Too LargeThe request payload exceeds the maximum size of 512 KiB.
500 Internal Server ErrorAn unexpected error occurred while processing the request.
503 Service UnavailableIngestion is currently disabled.
Note

Sources do not retain a history of pushed documents, to rebuild an index you must submit the full document set again.

Troubleshooting

Error or symptomResolution
tenant ID not found in JWT claimsUse Authorization: ApiKey <rawKey> with a Push API key, not a bearer token.
config not found or not publishedCheck the configuration ID, publication status, and SCAI instance associated with the key.
field "x" is not defined in configCheck the case-sensitive field name against the source schema.
requires a string valueSend the value as a JSON string, including numbers and booleans.
Invalid Sitecore datetimeUse the compact YYYYMMDDTHHMMSSZ format.
sc_url is required for site sourceInclude sc_url for a site source.
locale is required for multi-locale documentsInclude locale on every operation for a source with locales configured.
id is required for non-site sourceInclude id for a push or content source.
Pushed documents disappearA crawl or re-index rebuilt the source. Replay the push or use a push source for content that must persist.
If you have suggestions for improving this article, let us know!