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

# OData as a data source

> Bring data from any OData service (versions 2, 3 and 4) to Nekt.

OData (Open Data Protocol) is a standard for exposing data over REST that many business systems implement — SAP Gateway services, Microsoft Dataverse and Business Central, and custom services built on .NET, Java or Node.js, among others. This connector works with any service that speaks **OData version 2, 3 or 4**: it reads the service's `$metadata` document and turns each **entity set** into a table, with columns and types taken from the service itself.

<Note>For Microsoft Dynamics 365 Finance and Operations, use the dedicated [Microsoft Dynamics Finance and Operations](/sources/dynamics-fo) connector, which only asks for your environment URL and Microsoft Entra app.</Note>

## Before you start

You need:

* The **service URL** — the root address of the OData service, the one that lists its entity sets. Its metadata document is at `<service URL>/$metadata`. For example `https://services.odata.org/V4/Northwind/Northwind.svc` or `https://my-sap-host/sap/opu/odata/sap/API_BUSINESS_PARTNER`.
* Credentials for one of the supported authentication methods, from the administrator of the service.
* The service must be reachable from the internet.

## Configuring OData as a source

In the [Sources](https://app.nekt.ai/sources) tab, click the "Add source" button on the top right, then select OData from the list of connectors.

Click **Next** and you'll be prompted to add your access.

### 1. Add account access

* **Service URL**: The root URL of the OData service. If the service needs a parameter on every request (such as SAP's `sap-client=100`), you can include it in the URL or add it under **Query parameters**.
* **Authentication**: How the connector signs in:
  * **No authentication** — for public services.
  * **Basic** — a **Username** and **Password**.
  * **Bearer token** — a **Token** sent as `Authorization: Bearer <token>`.
  * **API key** — the **API key name** (header or query parameter name, for example `APIKey`), the **API key**, and whether it goes in a **header** or the **query string**.
  * **OAuth 2.0 client credentials** — the **Access token URL**, **Client ID**, **Client secret** and, if the server requires them, a **Scope** and extra **Token request parameters** (for example `audience`).
  * **Microsoft Entra ID (Azure AD) app** — the **Tenant ID**, **Client ID** and **Client secret** of an app registration. The scope defaults to `<service URL origin>/.default`.
* **Entities**: The entity sets to sync. Each becomes a stream. Use the collection name that appears in the service URL (for example `Customers`). For each entity set you can optionally set:

  * **Incremental field** — a date/time (or ever-increasing number) field the service updates when a record changes. With it, each run reads only records changed since the previous one.
  * **Filter** — an OData `$filter` expression, for example `Country eq 'Brazil'`.
  * **Fields** — the fields to read. Key fields and the incremental field are always included.

  Leave **Entities** empty to sync every entity set of the service.

Advanced settings:

* **Initial sync date**: For incremental entity sets, only records changed after this date are read on the first run.
* **Default incremental fields**: Field names to use as the incremental field of any entity set that has them, in order of preference.
* **OData version**: Detected automatically from the metadata; set it only if the service declares the wrong one.
* **Query parameters** and **Headers**: Added to every request.
* **Page size**, **Pagination** and **Order by keys**: See [Paging](#paging).
* **Incremental lookback (minutes)**: Each incremental sync re-reads records changed this many minutes before the previous position, to catch changes the service saves late. Off by default.
* **Request timeout**: How long to wait for each page before retrying (default 300 seconds).

Once you're done, click **Next**.

### 2. Select streams

Choose which data streams you want to sync. Each stream corresponds to one entity set. For faster extractions, select only the streams relevant to your analysis.

> Tip: The stream can be found more easily by typing its name.

Select the streams and click **Next**.

### 3. Configure data streams

Customize how you want your data to appear in your catalog. Select the desired Layer where the data will be placed, a Folder to organize it, a name for each table, and the type of sync.

* **Layer**: choose between the existing Layers on your catalog. This is where your extracted tables appear once the extraction runs successfully.
* **Folder**: a Folder can be created inside the selected Layer to group all tables created from this source.
* **Table name**: a name is suggested, but you can customize it. You can also add a **prefix** to all tables at once.
* **Sync Type**: choose between INCREMENTAL and FULL\_TABLE.
  * Incremental: available for entity sets with an incremental field; each extraction fetches only records changed since the last run.
  * Full table: each extraction fetches the whole entity set.

Once you are done configuring, click **Next**.

### 4. Configure data source

Describe your data source for easy identification within your organization, not exceeding 140 characters.

To define your [Trigger](https://docs.nekt.com/runs/scheduling-and-triggers), consider how often you want data to be extracted from this source.

Optionally, you can define additional settings such as Delta Log Retention and an additional [Full Sync](https://docs.nekt.com/get-started/core-concepts/types-of-sync#additional-full-sync) to complement the incremental extractions.

Once you are ready, click **Next** to finalize the setup.

### 5. Check your new source

You can view your new source on the [Sources](https://app.nekt.ai/sources) page. If needed, manually trigger the source extraction by clicking the arrow button. Once executed, your data appears in your Catalog.

<Warning>For you to be able to see it on your [Catalog](https://app.nekt.ai/catalog), you need at least one successful source run.</Warning>

# Streams and Fields

Streams are discovered from the service's `$metadata`: one stream per entity set, named in snake\_case (`SalesOrders` becomes `sales_orders`). Columns keep the names the service publishes, and the entity key becomes the table's primary key. When an entity set holds several record types (derived types), their extra fields are included too.

## How columns are represented

| OData type | Column type |
| - | - |
| `Edm.String`, `Edm.Guid`, enumerations, `Edm.TimeOfDay`, `Edm.Duration` | Text |
| `Edm.Binary` | Text (base64) |
| `Edm.Int16`, `Edm.Int32`, `Edm.Int64`, `Edm.Byte` | Integer |
| `Edm.Decimal`, `Edm.Double`, `Edm.Single` | Number |
| `Edm.DateTimeOffset`, `Edm.DateTime` | Timestamp (UTC) |
| `Edm.Date` | Date |
| Complex types, collections, geographic types | Text containing JSON |

<Note>`Edm.DateTime` values carry no time zone in OData versions 2 and 3; they are stored as UTC.</Note>

Navigation properties (links to related entities) are not expanded — sync the related entity set as its own stream instead.

## Paging

The **Pagination** setting chooses how each entity set is read page by page:

| Option | How it reads | When to use |
| - | - | - |
| **Server** (default) | Follows the address of the next page that the service returns. | Most services. |
| **Keyset** | Asks for records after the last key read (`$filter` on the key, **Page size** records per request). Stays correct while records are added, changed or deleted during the sync. | Entity sets with a single-field key, especially large ones. Others fall back to Offset. |
| **Offset** | Reads pages with `$top`/`$skip`. | Services that never page on their own (they return everything, or cut the result silently). |
| **Automatic** | Keyset for entity sets with a single numeric key, Server for the others. | |

Records are always sorted by the entity key (**Order by keys**, on by default), so pages stay stable. Turn it off only if the service rejects sorting. If a service ignores the paging parameters and keeps returning the same records, the sync stops with an error instead of looping; choose another **Pagination** option.

## Incremental sync

For an entity set with an incremental field, each run asks only for records whose field is equal to or later than the last value seen (minus the **Incremental lookback**, if set). Records whose incremental field does not change on update, records whose incremental field is empty, and deleted records are not detected — use FULL\_TABLE (or an additional Full Sync) for those entity sets.

If you change an entity set's **Filter** or **Incremental field**, its next sync starts again from the **Initial sync date**, so records that the new filter now includes are loaded too.

Only text, number and date/time fields can be incremental fields. Enumerations, GUIDs and durations cannot.

## Troubleshooting

* **"The service URL did not return an OData metadata document"** — the URL does not point to the service root. Open `<service URL>/$metadata` in a browser; it must show an XML document starting with `edmx:Edmx`.
* **"These entity sets were not found"** — the sync stops when an entity set listed in **Entities** does not exist on the service, so its table is never left silently outdated. Check the names (the collection names listed at the service URL), or remove the ones that no longer exist.
* **Access denied for an entity set** — the account used by the connector lacks read permission on it. Grant it, or remove the entity set from **Entities**.
* **The service is throttling** — the connector waits the time the service asks for and continues; no data is lost.
