> ## 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.

# Repediu as a data source

> Bring stores, orders, customers, conversions, campaigns, ratings and coupons from Repediu to Nekt.

Repediu is a customer retention and repurchase CRM for restaurants and delivery businesses: RFV segmentation, WhatsApp, SMS and e-mail campaigns, cashback, and the attribution of sales to those campaigns. This connector reads the Repediu integration API (Open Delivery 2.0 and partner CRM routes) and brings, for every store that shares its data with your integration, the **orders** with their items, the **customer registry**, the **customer purchase profiles** (RFV status, frequency, ticket), the **conversions** attributed to campaigns, the **campaigns** and their **daily sending funnel**, the **ratings**, the **coupons** used, and the **daily sales**.

> [!NOTE]
>
> The connector only reads data. It never creates, changes or sends anything in Repediu.

## Configuring Repediu as a Source

In the [Sources](https://app.nekt.ai/sources) tab, click on the "Add source" button located on the top right of your screen. Then, select the Repediu option from the list of connectors.

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

### 1. Add account access

The connector uses the **Client ID** and **Client Secret** of a Repediu integration (Open Delivery API). Repediu issues them to the integrator during onboarding; there is no self-service screen, so ask Repediu's integrations team for them. One credential gives access to every store that activated the integration in the Repediu panel, so a single source reads all of them.

The following configurations are available:

* **Client ID**: the Client ID issued by Repediu.

* **Client Secret**: the Client Secret issued together with the Client ID.

* **Start Date** (advanced): the earliest date to extract. It applies to orders (by update date) and to conversions, ratings, coupons, daily sales and campaign statistics (by date). Stores, customers, customer profiles and campaigns are always read whole. Leave it empty to extract the whole history: orders since 2000, and the dated CRM tables since 2015 (Repediu's CRM data does not go further back).

* **Max Requests per Minute** (advanced): (Default: 55) how many requests per minute the connector makes to Repediu. Raise it only if Repediu confirms a higher limit for your credential; lower it to leave room for other integrations that use the same credential. See [API Limits & Performance](#api-limits-performance).

> [!NOTE]
>
> A store appears in this source only after it activates your integration in the Repediu panel. If a store deactivates it, Repediu stops serving its data: the incremental tables keep the rows read until then, while Merchants, which is replaced on every run, keeps only the stores that still share their data.

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

### 2. Select streams

Choose which data streams you want to sync. For faster extractions, select only the streams that are relevant to your analysis. You can select entire groups of streams or pick specific ones.

> 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 inside the layer, a name for each table (which will effectively contain the fetched data) and the type of sync.

* **Layer**: choose between the existing layers on your catalog. This is where you will find your new extracted tables as the extraction runs successfully.
* **Folder**: a folder can be created inside the selected layer to group all tables being created from this new data source.
* **Table name**: we suggest a name, but feel free to customize it. You have the option to add a **prefix** to all tables at once and make this process faster!
* **Sync Type**: every stream except Merchants supports INCREMENTAL, and that is the recommended type for them: each store keeps its own extraction point, so a store that joins later is read from the start. Campaigns is read whole on every run but loaded incrementally, so a store Repediu stops serving keeps its campaigns (and a deleted campaign stays in the table). Merchants is FULL\_TABLE: it is small and replaced on every run. Read more about Sync Types [here](https://docs.nekt.com/get-started/core-concepts/types-of-sync).

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. Repediu receives most sales in a daily batch, so **once a day** is usually enough; schedule it in the morning, after Repediu's nightly processing.

Optionally, you can define some additional settings:

* Configure Delta Log Retention and determine for how long we should store old states of this table as it gets updated. Read more about this resource [here](https://docs.nekt.com/get-started/core-concepts/resource-control).
* Determine when to execute an **Additional [Full Sync](https://docs.nekt.com/get-started/core-concepts/types-of-sync#additional-full-sync)**. A full sync reads every store's whole history again, holds each table in temporary storage until it is complete, and with many stores takes as long as the first run (see [API Limits & Performance](#api-limits-performance)). Leave it off for accounts with many stores or long histories: the incremental runs re-read recent days, and read a store's orders again from the start when orders arrive later with past dates. Use a full sync when a store's history of customers, daily sales, ratings or coupons is loaded into Repediu after the store was first synced (see [Data Quality Considerations](#data-quality-considerations)).

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 on the arrow button. Once executed, your data will appear 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.

# Streams and Fields

## Available streams

The table below lists every stream, its **slug** (the exact identifier to pass when creating the source via API) and a short description.

| Stream | Slug | Description |
| - | - | - |
| Merchants | `merchants` | Stores (merchants) that activated the integration, with their address. |
| Orders | `orders` | Order history of each store, with its items, amounts in cents and in reais, channel and customer. |
| Customers | `customers` | Customer registry of each store: name, contacts, birth date, addresses and communication consents. |
| CRM Customers | `crm_customers` | Purchase profile of each customer, without personal data: RFV status, number of purchases, total spent, average ticket, best weekday and opt-ins. |
| Conversions | `conversions` | Sales attributed to the relationship with the customer, linking campaign, customer and sale. |
| Coupons | `coupons` | Sales in which a coupon was used: code, value, date and customer. |
| Ratings | `ratings` | Ratings received by each store: stars, review, date and platform of origin. |
| Campaigns | `campaigns` | Registry of each store's campaigns: type, channel, status, period, audience segments and cost per send. |
| Campaign Stats | `campaign_stats` | Sending funnel per campaign and day: sent, delivered, read, errors, clicks, unsubscriptions and cost. |
| Sales Daily | `sales_daily` | Sales of each store aggregated per day: orders, gross revenue and average ticket. |

## Fields by stream

### Open Delivery

> **Merchants**
>
> Stores (merchants) that activated the integration, with their address.
>
> Table: `merchants` · Primary key: `id` · Sync: Full table
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `id` | String | Identifier (UUID) of the store in Repediu; the merchant\_id/store\_id of every other table. |
> | `name` | String | Name of the store. |
> | `status` | String | Status of the store in Repediu: OPEN when active, CLOSED otherwise. |
> | `basic_info_name` | String | Name of the store as registered in its basic information. |
> | `address_street` | String | Street of the store's address. |
> | `address_number` | String | Street number of the store's address. |
> | `address_district` | String | District (bairro) of the store's address. |
> | `address_city` | String | City of the store's address. |
> | `address_state` | String | State (UF) of the store's address. |
> | `address_postal_code` | String | Postal code (CEP) of the store's address. |
> | `address_country` | String | Country of the store's address (always BR) |

> **Orders**
>
> Order history of each store, with its items. Amounts in cents and in reais.
>
> Table: `orders` · Primary key: `store_id`, `id` · Sync: Incremental (by `updated_at`)
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `id` | String | Identifier of the order in Repediu (the saleId of conversions, coupons and ratings) |
> | `store_id` | String | Identifier (UUID) of the store that owns the order (the merchants id) |
> | `origin_channel` | String | Order modality: delivery, takeout, in\_store, own\_app, marketplace, qr\_code, kiosk or other. |
> | `channel` | String | Sales channel as free text, as registered at the origin (metadata.channel) |
> | `customer_id` | String | Identifier of the customer in Repediu (customer.identifier.value) |
> | `customer_identifier_type` | String | Type of the customer identifier (always custom) |
> | `customer_external_ids` | String (JSON) | Customer identifiers per system (JSON array of objects with source and value; the first is always source repediu) |
> | `total_amount_cents` | Integer | Total amount of the order in cents, as the API sends it. |
> | `total_amount_brl` | Number | Total amount of the order in reais (total\_amount\_cents / 100) |
> | `items_count` | Integer | Number of item lines in the order. |
> | `items` | String (JSON) | Items of the order (JSON array of objects with sku, name, quantity and unitPrice; unitPrice in cents) |
> | `metadata` | String (JSON) | Complementary data of the order (JSON object) |
> | `created_at` | Datetime | Date and time of the sale (UTC) |
> | `updated_at` | Datetime | Last update of the order (UTC), used as the incremental replication key. |

> **Customers**
>
> Customer registry of each store: contacts, birth date, addresses and communication consents.
>
> Table: `customers` · Primary key: `merchant_id`, `id` · Sync: Incremental (by `updated_at`)
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `id` | String | Identifier of the customer in Repediu (the customerId of the CRM tables) |
> | `merchant_id` | String | Identifier (UUID) of the store the customer came from. |
> | `identifier_type` | String | Type of the canonical identifier (always custom) |
> | `identifier_value` | String | Value of the canonical identifier (the customer id in Repediu) |
> | `external_ids` | String (JSON) | Customer identifiers per system (JSON array of objects with source and value; the first is always source repediu) |
> | `name` | String | Name of the customer. |
> | `phone` | String | First phone number among the customer's contacts. |
> | `email` | String | First e-mail address among the customer's contacts. |
> | `contacts` | String (JSON) | All contacts of the customer (JSON array of objects with type and value) |
> | `birth_date` | Date | Birth date of the customer. |
> | `addresses` | String (JSON) | Addresses of the customer (JSON array of delivery/billing addresses) |
> | `consents` | String (JSON) | Communication consents (JSON array of objects with purpose, channel, status, grantedAt and revokedAt) |
> | `metadata` | String (JSON) | Complementary data of the customer (JSON object; currently always empty) |
> | `created_at` | Datetime | When the customer was created (UTC) |
> | `updated_at` | Datetime | Last update of the customer (UTC), used as the incremental replication key. |

### Partner CRM

> **CRM Customers**
>
> Pseudonymised purchase profile of each customer: RFV status, purchases, total spent, average ticket and opt-ins.
>
> Table: `crm_customers` · Primary key: `merchant_id`, `customer_id` · Sync: Incremental (by `updated_at`)
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `merchant_id` | String | Identifier (UUID) of the store (the merchants id) |
> | `customer_id` | Integer | Identifier of the customer in the store (the id of the customers table) |
> | `first_purchase_at` | Datetime | First purchase of the customer (UTC; Repediu sends it in store-local time, America/Sao\_Paulo) |
> | `last_purchase_at` | Datetime | Last purchase of the customer (UTC; Repediu sends it in store-local time, America/Sao\_Paulo) |
> | `purchase_count` | Integer | Number of purchases of the customer. |
> | `total_spent` | Number | Total spent by the customer, in reais. |
> | `avg_ticket` | Number | Average ticket of the customer, in reais. |
> | `avg_days_between_purchases` | Integer | Days between first and last purchase divided by purchase\_count (integer division; 0 for a single purchase) |
> | `best_weekday` | Integer | Weekday on which the customer buys the most (0 = Sunday) |
> | `rfv_status` | String | RFV status of the customer, in Portuguese (e.g. Campeões, Fiéis, Em risco) |
> | `whatsapp_optin` | Boolean | Whether the customer accepts communication by WhatsApp. |
> | `email_optin` | Boolean | Whether the customer accepts communication by e-mail. |
> | `created_at` | Datetime | When the customer profile was created (UTC) |
> | `updated_at` | Datetime | Last update of the profile (UTC), used as the incremental replication key. |

> **Conversions**
>
> Sales attributed to the relationship with the customer, linking campaign, customer and sale.
>
> Table: `conversions` · Primary key: `merchant_id`, `conversion_id` · Sync: Incremental (by `converted_at`)
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `merchant_id` | String | Identifier (UUID) of the store (the merchants id) |
> | `conversion_id` | Integer | Identifier of the conversion. |
> | `sale_id` | Integer | Converted sale (the id of the orders table) |
> | `customer_id` | Integer | Customer who bought (the customer\_id of crm\_customers) |
> | `converted_at` | Datetime | When the sale happened (UTC; Repediu sends it in store-local time), used as the incremental replication key. |
> | `amount` | Number | Value of the sale, in reais. |
> | `is_reactivation` | Boolean | True when the customer was inactive and came back to buy. |
> | `campaign_message_id` | Integer | Campaign message that led to the sale (null outside campaigns) |
> | `campaign_id` | Integer | Campaign of origin (null when the conversion did not come from a campaign) |
> | `channel` | String | Channel of the message that generated the conversion (WhatsApp, SMS, Email...) |
> | `days_since_message` | Integer | Days between the message and the purchase. |
> | `rfv_status_at_conversion` | String | RFV status of the customer at the moment of the conversion. |
> | `attribution_window` | String (JSON) | Attribution window in days per RFV status at read time (JSON object: champion, loyal, promising, risk, lost) |

> **Coupons**
>
> Sales in which a coupon was used: code, value, date and customer.
>
> Table: `coupons` · Primary key: `merchant_id`, `sale_id`, `coupon` · Sync: Incremental (by `updated_at`)
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `merchant_id` | String | Identifier (UUID) of the store (the merchants id) |
> | `sale_id` | Integer | Sale with a coupon (the id of the orders table) |
> | `coupon` | String | Code of the coupon used in the sale. |
> | `customer_id` | Integer | Customer who used the coupon (the customer\_id of crm\_customers) |
> | `amount` | Number | Value of the sale, in reais. |
> | `sale_date` | Datetime | When the sale happened (UTC) |
> | `updated_at` | Datetime | Last update of the record (UTC), used as the incremental replication key. |

> **Ratings**
>
> Ratings received by each store: stars, review, date and platform of origin.
>
> Table: `ratings` · Primary key: `merchant_id`, `rating_id` · Sync: Incremental (by `rating_date`)
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `merchant_id` | String | Identifier (UUID) of the store (the merchants id) |
> | `rating_id` | Integer | Identifier of the rating. |
> | `sale_id` | Integer | Rated sale (the id of the orders table) |
> | `customer_id` | Integer | Customer who rated (the customer\_id of crm\_customers) |
> | `stars` | Integer | Rating given, in stars. |
> | `review` | String | Comment written by the customer, when there is one. |
> | `rating_date` | Datetime | When the rating was made (UTC), used as the incremental replication key. |
> | `integration_id` | String | Platform the rating came from (e.g. Ifood, AnotaAi, Google) |

### Campaigns

> **Campaigns**
>
> Registry of each store's relationship campaigns.
>
> Table: `campaigns` · Primary key: `merchant_id`, `campaign_id` · Sync: Incremental (by `updated_at`)
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `merchant_id` | String | Identifier (UUID) of the store (the merchants id) |
> | `campaign_id` | Integer | Identifier of the campaign (used by conversions and campaign\_stats) |
> | `name` | String | Name of the campaign. |
> | `type` | String | Type of the campaign, as registered in Repediu (free text) |
> | `channel` | String | Sending channel, as registered in Repediu (free text) |
> | `status` | String | Status of the campaign, as registered in Repediu (free text) |
> | `start_date` | Datetime | Start of the campaign (UTC; Repediu sends it in store-local time, America/Sao\_Paulo) |
> | `end_date` | Datetime | End of the campaign (UTC; Repediu sends it in store-local time); null when open-ended. |
> | `audience_segments` | String (JSON) | Audience segments of the campaign (JSON array of objects with segmentId and name) |
> | `cost_per_send` | Number | Cost per send in the campaign's channel, in reais (null when not priced) |
> | `updated_at` | Datetime | Last update of the campaign (UTC), used as the incremental replication key. |

> **Campaign Stats**
>
> Sending funnel per campaign and day: sent, delivered, read, errors, clicks and cost.
>
> Table: `campaign_stats` · Primary key: `merchant_id`, `campaign_id`, `date` · Sync: Incremental (by `date`)
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `merchant_id` | String | Identifier (UUID) of the store (the merchants id) |
> | `campaign_id` | Integer | Campaign (the campaign\_id of campaigns) |
> | `date` | Date | Day (store-local), used as the incremental replication key. |
> | `sent` | Integer | Messages sent. |
> | `delivered` | Integer | Messages delivered. |
> | `read` | Integer | Messages read. |
> | `error` | Integer | Messages with error. |
> | `pending` | Integer | Messages pending. |
> | `opened` | Integer | Messages opened (null in channels that do not measure opening) |
> | `clicked` | Integer | Clicks (null in channels that do not measure clicks) |
> | `unsubscribed` | Integer | Unsubscriptions (null in channels that do not measure them) |
> | `total_cost` | Number | Cost of the day's sending, in reais. |

### Daily sales

> **Sales Daily**
>
> Sales of each store aggregated per day: orders, gross revenue and average ticket.
>
> Table: `sales_daily` · Primary key: `merchant_id`, `date` · Sync: Incremental (by `date`)
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `merchant_id` | String | Identifier (UUID) of the store (the merchants id) |
> | `date` | Date | Day (store-local), used as the incremental replication key. |
> | `orders_count` | Integer | Number of orders of the day. |
> | `gross_revenue` | Number | Gross revenue of the day, in reais. |
> | `avg_ticket` | Number | Average ticket of the day, in reais. |
> | `timezone` | String | Time zone used to close each day (e.g. America/Sao\_Paulo) |

## Implementation Notes

### Data Quality Considerations

* Every table except `merchants` has a column with the store it belongs to (`store_id` in `orders`, `merchant_id` elsewhere); join it to `merchants.id`.
* Keys across tables: `orders.id` is the `sale_id` of `conversions`, `coupons` and `ratings` (a string in `orders`, a number elsewhere); `customers.id` is the `customer_id` of the CRM tables. Customer ids belong to a store: join on the store column too.
* All dates and times are in UTC. Repediu sends the CRM times (purchases, conversions, campaign periods) in store-local time (America/Sao\_Paulo); the connector converts them to UTC. Convert back to Brasília time before grouping by day to match the Repediu panel. `date` in `sales_daily` and `campaign_stats` is already the store-local day.
* Money: `orders` has `total_amount_cents` (as Repediu sends it) and `total_amount_brl` (in reais); the item prices inside `items` are in cents. Amounts in the CRM tables are in reais.
* `crm_customers` has no name, phone or e-mail by design (Repediu pseudonymises it); personal data is in `customers`.
* `opened`, `clicked` and `unsubscribed` in `campaign_stats` are empty (not zero) for channels that do not measure them.
* Late data is read again on every run: 2 days of updates for orders, customers, customer profiles and coupons; 10 days for conversions and ratings; 7 days for daily sales; 30 days for campaign statistics (delivery and read receipts keep arriving).
* History loaded into Repediu after a store was first synced: every run checks whether orders with past dates arrived, and reads that store's orders again from the start when they did (the run log says so). Customers get the same check, but it can miss late customers when, in the same days, as many old customers were updated. Daily sales, ratings, coupons, conversions and campaign statistics loaded with dates older than their re-read window are only brought by a full sync.
* Coupons: one row per sale and coupon code (a sale can carry more than one code).

### API Limits & Performance

* Repediu limits requests per credential. The connector makes at most **Max Requests per Minute** requests (default 55) and waits when Repediu asks it to slow down. A daily run needs about 15 requests per store, the first run about 70 (daily sales, campaign statistics, conversions, ratings and coupons are read one calendar year at a time since 2015 or since the Start Date). At the default pace:

  | Stores | Daily run | First run |
  | :- | :- | :- |
  | 50 | about 15 minutes | about 1 hour |
  | 200 | about 1 hour | about 4 hours |
  | 1,000 | about 4.5 hours | about 21 hours |

  Stores with long order histories add requests on top. If Repediu confirms a higher limit, raise **Max Requests per Minute** (at 300 per minute, 1,000 stores take about 50 minutes a day).
* A full sync reads everything before writing each table, so a table is never replaced with part of its data.
* Not extracted: Repediu's ready-made metrics (totals and rates per period or campaign, which can be computed from the tables above), the per-customer detail with favorite products, and the Repediu data-sending API.

## Troubleshooting

| Error or symptom | What it means | What to do |
| :- | :- | :- |
| "Repediu rejected the Client ID / Client Secret" | The credential is wrong, was revoked, or was not copied whole. | Check both values with Repediu's integrations team and update the source. |
| "Repediu reports no store available to this credential" | No store has activated the integration yet, or the credential lacks the `od.crm` permission. | Ask the stores to activate the integration in the Repediu panel, or ask Repediu to review the credential. Nothing is loaded until then. |
| A stream was skipped because the credential is not allowed to read it | The credential lacks the permission of that route. Its table was not updated. | Ask Repediu's integrations team for the permission, or deselect the stream. |
| "The store ... stopped sharing its data with this integration" | The store deactivated the integration during the run. Incremental tables keep its rows and continue when it comes back; a table read in full stops the run. | No action needed if the deactivation was intended; the next run reads the current list of stores. |
| "Repediu answered 'not found' for the closed store ..." (warning) | A store marked closed in Repediu could not be read on that stream. The incremental table keeps its rows; the other stores were read. | No action needed for a closed store. If it is still operating, check its status with Repediu. |
| "The store ... is closed in Repediu and its data could not be read ... the sync stopped" | In a full sync, a closed store could not be read on that stream; the table would lose that store's rows, so the run stopped before writing it. | Use incremental sync for the stream and avoid full syncs while the store is closed; contact Nekt support if the store is still operating. |
| "Repediu answered 'not found' for the details of the closed store ... the sync stopped" | Merchants is replaced on every run and could not read that closed store's details, so the run stopped before writing it. | Contact Nekt support if this repeats. |
| "... older record(s) of the store ... appeared in Repediu with past dates" | Orders or customers were loaded into Repediu with past dates (for example, a history import). | No action needed: that store's orders or customers are read again from the start in this run, which takes longer. |
| "'Max Requests per Minute' must be a whole number ..." | The setting is outside 1 to 1,200. | Fix it in the source settings (or clear it to use 55). |
| The run stops saying a list was inconsistent or a filter was not applied | Repediu returned a list that changed or contradicted itself during the read; nothing partial was loaded. | Run the source again. If it persists, contact support with the source slug, the run ID, and the time with timezone. |

## Skills for agents

<Snippet file="agent-skills-intro.mdx" />

> **[Download Repediu skills file](/sources/repediu.md)**
>
> Repediu connector documentation as plain markdown, for use in AI agent contexts.


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