> ## Documentation Index
> Fetch the complete documentation index at: https://docs.frontic.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Overview

The Ingest API powers data ingestion in your Frontic project. Pre-built connectors automatically use this API to process updates from your data pipeline into your [Data Feeds](https://docs.frontic.com/data-integration/ingest.md#data-feeds).

For scenarios where you need more control or when a pre-built connector isn't available, you can directly interact with the Ingest API through a [Custom Integration](https://docs.frontic.com/connectors/custom.md).

![Ingest API Hero](https://mintcdn.com/frontic/34vlQbUxJTTktEkF/images/hero-ingest.png?fit=max\&auto=format\&n=34vlQbUxJTTktEkF\&q=85\&s=f843fb1fe851d0e8a3cfbf3dcc33cb52)

## Base URL

Each integration has a unique Ingest API URL. Find yours in the admin app under integration settings.

```
https://ingest-{integration-id}.frontic.com
```

All record-level routes are prefixed with `/ingest/`, so the full URL pattern for a feed call is `https://ingest-{integration-id}.frontic.com/ingest/{feed-token}/{action}`.

## Authentication

All requests to the Ingest API require an API key.

### Create an Ingest API key

In the admin app, open **Settings → API Keys**, click **Add API Key**, and select **Ingest API**. The key shows once on creation - copy it into your secret store before navigating away. You can create multiple keys (one per integration / environment) and rotate them independently.

The same dialog creates **Fetch API** keys and the project's [Bypass Token](https://docs.frontic.com/project-settings/domains.md#bypass-token). The Bypass Token works the other way round: it identifies Frontic to your own storefront instead of protecting a Frontic API.

**Authorization** `string` *required*

Your Frontic Ingest API key. Include this header on every request to the Ingest API.

```bash Example theme={"theme":"css-variables"}
curl -X POST https://ingest-{integration-id}.frontic.com/ingest/{feed-token}/upsert \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"id": "product-123", "name": "Example"}'
```

> [accordion] Alternate: apiKey query parameter
>
> When the `Authorization` header isn't an option (e.g. webhook callers that only support fixed URLs), you can pass the key as the `apiKey` query parameter instead:
>
> ```
> https://ingest-{integration-id}.frontic.com/ingest/{feed-token}/upsert?apiKey=YOUR_API_KEY
> ```
>
> Prefer the header - query-string secrets get logged by proxies, browsers, and analytics. Only use the query parameter when the header path isn't available.

## Available Endpoints

Two interaction modes exist:

* **Push intents** - your system sends data into Frontic. Use these when you control the source and want to push changes as they happen. Available: [Upsert](https://docs.frontic.com/reference/ingest-api/upsert.md), [Patch](https://docs.frontic.com/reference/ingest-api/patch.md), [Delete](https://docs.frontic.com/reference/ingest-api/delete.md).
* **Trigger intents** - your system signals Frontic to pull data, and Frontic uses the integration's connector logic to fetch the actual records. Useful for webhook flows where the source can notify changes but expects Frontic to do the fetch. Available: [Trigger Fetch](https://docs.frontic.com/reference/ingest-api/fetch.md), [Trigger Fetch List](https://docs.frontic.com/reference/ingest-api/fetch-list.md). Requires the Data Feed to be configured with method **trigger** or **polling** rather than **ingest**.

> [card] [Upsert](https://docs.frontic.com/reference/ingest-api/upsert.md)
>
> Create or replace a record (push)

> [card] [Patch](https://docs.frontic.com/reference/ingest-api/patch.md)
>
> Incrementally update a record (push)

> [card] [Delete](https://docs.frontic.com/reference/ingest-api/delete.md)
>
> Remove records from your feed (push)

> [card] [Trigger Fetch](https://docs.frontic.com/reference/ingest-api/fetch.md)
>
> Signal Frontic to pull a single record (trigger)

> [card] [Trigger Fetch List](https://docs.frontic.com/reference/ingest-api/fetch-list.md)
>
> Signal Frontic to pull a list of records (trigger)

### Generic intent endpoint

The verb-specific routes above are convenience shortcuts. Frontic also exposes a generic endpoint that accepts any intent as part of the path:

```
POST /ingest/{feed-token}/{intent}
```

Where `{intent}` is one of `upsert`, `patch`, `delete`, `fetch`, or `fetch-list`. The behaviour matches the corresponding shortcut. Most callers should use the verb-specific routes - the generic endpoint is for tooling that builds the intent dynamically.

### Health check

```
GET /ingest/status
```

Returns `{"status": "ok"}` when the Ingest API is reachable. It takes no API key and reads nothing from the URL, so a `200` confirms that the service is up and nothing more. It does not validate your integration ID, your feed token, or your key. Any Ingest subdomain answers it. To check those, use the verify request below.

### Verify your configuration

```
HEAD /ingest/{feed-token}/{intent}
```

Send a `HEAD` request to any endpoint you intend to call and the Ingest API checks your URL, API key, and intent without accepting or storing a record. Use it as a preflight when wiring up an integration, so a misconfigured key or URL surfaces before you push data.

| Code | When |
| - | - |
| `200` | The integration ID exists, the API key is valid for it, and the intent is recognised |
| `401` | The API key is missing or wrong, or the integration ID in the subdomain doesn't exist. The response doesn't say which |
| `422` | The intent is not one of `upsert`, `patch`, `delete`, `fetch`, or `fetch-list` |

A `200` does not confirm the feed token. The verify request checks that the intent is a real intent, not that the feed exists or that the intent suits how that feed is configured. Real calls don't check the token either - see [Accepted but not processed](#accepted-but-not-processed).

```bash theme={"theme":"css-variables"}
curl -I 'https://ingest-<integration-id>.frontic.com/ingest/<feed-token>/upsert' \
  -H 'Authorization: YOUR_API_KEY'
```

## Response Format

All record-level endpoints return a JSON response containing a correlation ID:

```json theme={"theme":"css-variables"}
{
  "correlation-id": "22c8f6f9-2a62-4e18-81a5-33c207dd967d"
}
```

**correlation-id** `string`

Unique identifier to track this data change through Frontic's processing pipeline. Save this ID if you need to debug or inquire about a specific operation.

### Errors

A rejected request returns an error body instead:

```json theme={"theme":"css-variables"}
{
  "error": "Payload is invalid JSON",
  "code": "invalid_payload",
  "details": [],
  "correlationId": "22c8f6f9-2a62-4e18-81a5-33c207dd967d"
}
```

**code** `string`

Error code from Frontic. Listed under [Error Handling](#error-handling).

**error** `string`

A readable description of the problem.

**details** `object`

Extra values for the error, such as the limit and usage for `ingest_api_limit_exceeded`. Often empty.

**correlationId** `string`

Identifier of the failed request. Note the spelling: error bodies use `correlationId`, successful responses use `correlation-id`.

## Error Handling

> [accordion] 401 Unauthorized
>
> Code `unauthorized`. The API key is missing or wrong, or the integration ID in the subdomain doesn't exist. The response doesn't say which of the two is wrong. Check the key in the `Authorization` header (or the `apiKey` query parameter) and the integration ID in the URL.

> [accordion] 422 Unprocessable Entity
>
> The `code` field says why:
>
> * `ingest_api_limit_exceeded` - your team has used up the **API Updates** allowance of its plan (see [Quotas](https://docs.frontic.com/admin/billing-and-plans.md#quotas)). `details` carries `limit` and `usage`. While the limit is exceeded, every push and trigger call is rejected, deletes included. The verify request still answers. Upgrade the plan to raise the limit.
> * `invalid_intent` - the intent in the URL is not one of `upsert`, `patch`, `delete`, `fetch`, or `fetch-list`.
> * `invalid_payload` - the request body is not valid JSON. An empty body counts as invalid.

> [accordion] 500 Internal Server Error
>
> Something failed on Frontic's side. The body carries only `error` and `correlationId`. Contact support with the `correlationId`.

### Accepted but not processed

The Ingest API accepts a call and returns `200` with a `correlation-id` before it looks at the feed or the record. The checks below run later, during processing. When one fails, there is no error response: the records just never appear in the feed.

* The feed token in the URL doesn't exist.
* An `upsert` or `patch` goes to a feed whose method isn't **ingest**.
* A `fetch` or `fetch-list` goes to a feed whose method isn't **trigger** or **polling**.
* A `fetch-list` goes to an integration whose connector doesn't support list fetches.
* A record has no Source ID.

If a push returned `200` but the records are missing, open the feed's **Recent Records** and work through [Troubleshooting](https://docs.frontic.com/connectors/custom.md#troubleshooting).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.