> ## 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](/data-integration/ingest#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](/connectors/custom).

<Frame>
  <img src="https://mintcdn.com/frontic/34vlQbUxJTTktEkF/images/hero-ingest.png?fit=max&auto=format&n=34vlQbUxJTTktEkF&q=85&s=f843fb1fe851d0e8a3cfbf3dcc33cb52" alt="Ingest API Hero" width="1910" height="665" data-path="images/hero-ingest.png" />
</Frame>

## 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-id}/{action}`.

## Authentication

All requests to the Ingest API require an API key.

### Create an Ingest API key

In the admin app, open **Settings → Secrets**, 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.

<ParamField header="Authorization" type="string" required>
  Your Frontic Ingest API key. Include this header on every request to the Ingest API.
</ParamField>

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

<Accordion title="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-id}/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.
</Accordion>

## 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](/reference/ingest-api/upsert), [Patch](/reference/ingest-api/patch), [Delete](/reference/ingest-api/delete).
* **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](/reference/ingest-api/fetch), [Trigger Fetch List](/reference/ingest-api/fetch-list). Requires the Data Feed to be configured with method **trigger** or **polling** rather than **ingest**.

<CardGroup cols={3}>
  <Card title="Upsert" icon="plus" href="/reference/ingest-api/upsert">
    Create or replace a record (push)
  </Card>

  <Card title="Patch" icon="pen" href="/reference/ingest-api/patch">
    Incrementally update a record (push)
  </Card>

  <Card title="Delete" icon="trash" href="/reference/ingest-api/delete">
    Remove records from your feed (push)
  </Card>

  <Card title="Trigger Fetch" icon="bell" href="/reference/ingest-api/fetch">
    Signal Frontic to pull a single record (trigger)
  </Card>

  <Card title="Trigger Fetch List" icon="bell-on" href="/reference/ingest-api/fetch-list">
    Signal Frontic to pull a list of records (trigger)
  </Card>
</CardGroup>

### 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-id}/{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.

## Response Format

All endpoints return a JSON response containing a correlation ID:

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

<ResponseField name="correlation-id" type="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.
</ResponseField>

### Errors

Endpoints may return errors for your requests. Those are identified with additional fields:

<ResponseField name="code" type="string">
  Error code from Frontic. Can be used to inquire about the error.
</ResponseField>

<ResponseField name="error" type="string">
  Error information from Frontic. Can indicate the issue.
</ResponseField>

<ResponseField name="details" type="object">
  Error details from Frontic. Can indicate a specific field or value that is relevant for the error.
</ResponseField>

## Error Handling

<AccordionGroup>
  <Accordion title="401 Unauthorized">
    Your API key is missing or invalid. Ensure you're passing the correct key in the `Authorization` header.
  </Accordion>

  <Accordion title="400 Bad Request">
    The request body is missing required fields. Check that your JSON request body includes the `id` field.
  </Accordion>

  <Accordion title="404 Not Found">
    The specified feed ID doesn't exist. Verify the feed ID in your request URL.
  </Accordion>

  <Accordion title="422 Unprocessable Entity">
    Response body gives error codes:

    * `invalid_payload` - Invalid payload (e.g. malformed JSON)
    * `invalid_intent` - Unknown intent (should be one of `upsert`, `patch`, `delete`, `fetch` or `fetch-list`)
  </Accordion>

  <Accordion title="429 Too Many Requests">
    You've exceeded the rate limit. Wait before retrying. See [Limits](/admin/limits) for more information.
  </Accordion>
</AccordionGroup>
