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

# Register provider resources

> Create or update source records from provider resources. Step 2 of the connected-source flow.

Creates or updates source records for the resources you discovered with [List provider resources](/en/api-reference/list-provider-resources), and returns the resulting source IDs in the wire-format fields `addedDocumentIds` and `updatedDocumentIds`.

<Warning>
  This route does **not** queue ingestion by itself. It only creates source records. To actually start processing, call [Ingest sources](/en/api-reference/ingest-sources) next, passing the IDs returned by this route.
</Warning>

## Headers

<ParamField header="Authorization" type="string" required>
  Bearer token containing your Fini workspace API key. Format: `Bearer fini_...` The key needs `write` scope.
</ParamField>

<ParamField header="Content-Type" type="string" required>
  `application/json`
</ParamField>

## Path parameters

<ParamField path="provider" type="string" required>
  Provider name. Supported values: `notion`, `zendesk`, `confluence`. Must match a provider that's already connected in the workspace.
</ParamField>

## Body parameters

<ParamField body="resources" type="array" required>
  Array of resource objects to register. Each resource accepts the fields below.

  <Expandable title="resource object">
    <ParamField body="originalUrl" type="string" required>
      Provider URL for the resource.
    </ParamField>

    <ParamField body="title" type="string" required>
      Resource title.
    </ParamField>

    <ParamField body="externalId" type="string" required>
      Provider-specific identifier (e.g., the Notion page ID).
    </ParamField>

    <ParamField body="mimeType" type="string" required>
      Resource MIME type. Typically taken from the discovery response.
    </ParamField>

    <ParamField body="storageUrl" type="string">
      Optional internal storage URL.
    </ParamField>

    <ParamField body="object" type="string">
      Optional provider-specific type (e.g., Notion `object: "page"`).
    </ParamField>
  </Expandable>
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST \
    --url 'https://api-prod.usefini.com/v2/documents/public/resources/notion' \
    --header 'Authorization: Bearer fini_your_api_key' \
    --header 'Content-Type: application/json' \
    --data '{
      "resources": [
        {
          "originalUrl": "https://www.notion.so/fini/Billing-FAQ-123456",
          "title": "Billing FAQ",
          "externalId": "123456",
          "mimeType": "text/markdown",
          "object": "page"
        }
      ]
    }'
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api-prod.usefini.com/v2/documents/public/resources/notion",
      headers={
          "Authorization": "Bearer fini_your_api_key",
          "Content-Type": "application/json",
      },
      json={
          "resources": [
              {
                  "originalUrl": "https://www.notion.so/fini/Billing-FAQ-123456",
                  "title": "Billing FAQ",
                  "externalId": "123456",
                  "mimeType": "text/markdown",
                  "object": "page",
              }
          ]
      },
  )
  data = response.json()
  ```

  ```javascript Node.js theme={null}
  const response = await fetch(
    "https://api-prod.usefini.com/v2/documents/public/resources/notion",
    {
      method: "POST",
      headers: {
        Authorization: "Bearer fini_your_api_key",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        resources: [
          {
            originalUrl: "https://www.notion.so/fini/Billing-FAQ-123456",
            title: "Billing FAQ",
            externalId: "123456",
            mimeType: "text/markdown",
            object: "page",
          },
        ],
      }),
    }
  );
  const data = await response.json();
  ```
</RequestExample>

## Response

<ResponseField name="addedDocumentIds" type="array">
  Source IDs for resources that were newly registered.
</ResponseField>

<ResponseField name="updatedDocumentIds" type="array">
  Source IDs for resources that already existed in the workspace and had their metadata updated.
</ResponseField>

<ResponseExample>
  ```json 200 OK theme={null}
  {
    "addedDocumentIds": [
      "5d9f67a8-d853-4af4-b7ce-23ebba1245e5"
    ],
    "updatedDocumentIds": []
  }
  ```

  ```json 400 Bad Request theme={null}
  {
    "statusCode": 400,
    "message": "Provider not supported on public route",
    "error": "Bad Request"
  }
  ```

  ```json 403 Forbidden theme={null}
  {
    "statusCode": 403,
    "message": "API key is missing the required `write` scope",
    "error": "Forbidden"
  }
  ```
</ResponseExample>

## Next step

Pass the returned `addedDocumentIds` and `updatedDocumentIds` into [Ingest sources](/en/api-reference/ingest-sources):

* Put new IDs into `documentIdsToAdd` to ingest them for the first time.
* Put existing IDs into `documentIdsToRefresh` to re-process them.

Without that follow-up call, the source records exist but no content gets processed.

## Errors

<AccordionGroup>
  <Accordion title="400 Bad Request" icon="circle-exclamation">
    The provider is not supported on the public route, not connected in the workspace, or one of the resource objects is missing required fields (`originalUrl`, `title`, `externalId`, `mimeType`).
  </Accordion>

  <Accordion title="401 Unauthorized" icon="lock">
    The API key is missing, malformed, revoked, or invalid. Confirm `Authorization: Bearer fini_...` with the full key.
  </Accordion>

  <Accordion title="403 Forbidden" icon="shield-halved">
    The API key doesn't include the `write` scope, or it's scoped to a different workspace.
  </Accordion>

  <Accordion title="The response returned IDs but nothing is processing" icon="circle-question">
    Expected. This route only creates source records. It doesn't queue ingestion. Call [Ingest sources](/en/api-reference/ingest-sources) with the returned IDs to start processing.
  </Accordion>
</AccordionGroup>
