Activity, Export, and Sync
Audit who did what on an order, export bulk data to CSV for reporting, and force a sync against connected channels.
Base URL
https://api.fenicia.ioAll endpoints require Authorization: Bearer fkapi_....
Order activity history
Returns the chronological trace of the order: creation events, state transitions, shipments, cancellations, refunds, etc. Requires orders:read.
orderIdstringrequiredOrder ID (path).
limitnumberMaximum number of entries per page. Default: 50.
offsetnumberNumber of entries to skip from the start. Default: 0.
{
"data": {
"entries": [
{
"id": "act_65f3a1b2c4d5e6f7a8b9c0f1",
"eventType": "status_changed",
"source": "api",
"timestamp": "2026-04-10T14:30:00.000Z",
"userId": "usr_123",
"userName": "María López",
"userEmail": "maria@merchant.example.com",
"userRole": "admin",
"details": { "fromStatus": "accepted", "toStatus": "preparing" }
},
{
"id": "act_65f3a1b2c4d5e6f7a8b9c0f0",
"eventType": "order_accepted",
"source": "system",
"timestamp": "2026-04-10T13:10:00.000Z"
}
],
"totalCount": 14,
"hasMore": true,
"pagination": { "limit": 50, "offset": 0, "nextOffset": 50 }
}
}
Real shape of an entry
Each entry is { id?, timestamp, eventType, source, details?, userId?, userName?, userEmail?, userRole?, quotaImpact? }. The event field is eventType, not action; transition data (for example fromStatus/toStatus) goes inside details when applicable, not as top-level fields.
curl "https://api.fenicia.io/orders/65f3a1b2c4d5e6f7a8b9c0d1/activity-log?limit=100&offset=0" \
-H "Authorization: Bearer fkapi_your_api_key"Tip
To paginate forward, use pagination.nextOffset as the next offset. When hasMore is false, there are no more entries.
Export orders to CSV
Exports the orders matching the filters to a CSV file. Requires orders:export.
columnsstringrequiredComma-separated list of column paths to include. Supports nested paths, e.g. customerInfo.email.
localestringLocale used to format values in the CSV. Default: es.
maxRecordsnumberMaximum number of records to export. Default: 10000.
startDatestringISO start date of the range (inclusive).
endDatestringISO end date of the range (inclusive).
orderStatusstringFilter by order status. Also accepts the status alias.
channelIdsstringFilter by one or more channels.
metafieldsstringAdditional filter by metafields, in JSON format.
Content-Type: text/csv
Content-Disposition: attachment; filename="pedidos-2026-04-11.csv"
externalId,customerInfo.email,total,orderStatus
1001,ana@example.com,1500.00,accepted
1002,luis@example.com,780.50,fulfilled
There is no format parameter
This endpoint always returns raw CSV (Content-Type: text/csv), never JSON. There is no format parameter to choose another output — if you send one, it's ignored. columns is required: without it, the API responds with a validation error.
The date range uses startDate / endDate, not from / to
This endpoint reuses the same filter normalizer as GET /orders (see List Orders). The date range is filtered with startDate and endDate — the names from/to don't exist in this API.
curl "https://api.fenicia.io/orders/export?columns=externalId,customerInfo.email,total,orderStatus&startDate=2026-04-01&endDate=2026-04-30" \
-H "Authorization: Bearer fkapi_your_api_key" \
-o pedidos.csvList orders with overdue settlement
Paginated list of orders whose channel settlement is overdue beyond the configured grace period. Requires orders:read.
pagenumberPage number.
limitnumberItems per page.
gracePeriodDaysnumberGrace period in days before a settlement is considered overdue.
channelIdstringFilter by channel.
startDatestringISO start date of the range (inclusive).
endDatestringISO end date of the range (inclusive).
{
"data": [
{
"_id": "65f3a1b2c4d5e6f7a8b9c0d1",
"externalId": "FEN-10042",
"channelId": "chn_shopify_01",
"orderStatus": "delivered",
"total": 1986.26
}
],
"meta": {
"pagination": { "page": 0, "limit": 20, "total": 6, "totalPages": 1, "hasMore": false }
}
}
Previously undocumented endpoint
This endpoint exists and works in the public API, but had no documentation until this page. Unlike the abandoned carts listing, it follows the domain's standard envelope: { data: [...], meta: { pagination } }.
Export orders with overdue settlement
Exports to CSV the orders with overdue settlement, with the same filters as the listing. Requires orders:export.
gracePeriodDaysnumberGrace period in days before a settlement is considered overdue.
channelIdstringFilter by channel.
startDatestringISO start date of the range (inclusive).
endDatestringISO end date of the range (inclusive).
Content-Type: text/csv
Content-Disposition: attachment; filename="liquidacion-vencida-2026-04-11.csv"
Previously undocumented endpoint
Same as GET /orders/settlement-overdue, this endpoint exists and works but had no documentation until this page.
Sync all orders
Queues an asynchronous sync of orders from all connected, active channels. Requires orders:manage.
{}{
"data": {
"message": "Sync initiated",
"status": "processing",
"channelCount": 4
}
}
No body required; the message travels in English
This endpoint doesn't read any field from the body — send {} or no body at all, it makes no difference. The real response carries channelCount (number of channels queued), not channelsQueued, and the message field is literally "Sync initiated" (in English, exactly as the handler returns it) — don't translate it when showing it to your end user without first confirming it's a data value, not an i18n key. It also always includes status: "processing".
curl -X POST https://api.fenicia.io/orders/sync \
-H "Authorization: Bearer fkapi_your_api_key"Sync a single order
Forces the sync of a specific order against its source channel. Requires orders:manage.
orderIdstringrequiredOrder ID.
{}{
"data": {
"message": "Order sync initiated",
"status": "processing",
"orderId": "65f3a1b2c4d5e6f7a8b9c0d1"
}
}
{ "error": { "code": "sync:channel_not_found", "message": "Cannot sync order 65f3a1b2c4d5e6f7a8b9c0d1" } }
curl -X POST https://api.fenicia.io/orders/65f3a1b2c4d5e6f7a8b9c0d1/sync \
-H "Authorization: Bearer fkapi_your_api_key"Tip
Both sync endpoints are asynchronous. Subscribe to the order.updated webhook or poll GET /orders/{orderId} again to detect when it finishes.
Errors
| Code | Status | Description |
|---|---|---|
orders:not_found | 404 | No order with that ID exists in your tenant. |
sync:channel_not_found | 404 | The channel to sync doesn't exist or doesn't belong to the tenant. |
sync:channel_disabled | 409 | The channel exists but is disabled. |
sync:integration_error | 502 | The channel's integration returned an error while syncing. |
sync:rate_limited | 429 | The allowed sync limit was reached in the current window. |
validation:invalid_pagination | 400 | page, limit, or offset has a value out of range. |
validation:invalid_date_range | 400 | startDate is later than endDate. |
auth:invalid_token | 401 | The API key is invalid or was revoked. |
auth:permission_denied | 403 | The API key doesn't have the required permission (orders:read, orders:export, or orders:manage, depending on the endpoint). |