Exports and offboarding
Everything belonging to one owner, or to the whole account, in a ZIP. And how to part ways with an owner or with Kinapi without leaving anyone without their records.
Why it exists
The owner (titular) of an accommodation must keep the traveller reports for three years after the stay ends (Article 5.3 of RD 933/2021). When you stop managing an owner, or close your Kinapi account, that owner has to be able to take everything with them: the signed reports, the proof that they were filed, the contracts and the evidence of every signature. An export gathers it in a ZIP, per owner, per property or for the whole account.
Request an export
/exports| Field | Type | Description |
|---|---|---|
ownerId | string | The bookings of every property of this owner (id from /owners), including their deactivated properties and the bookings that came in under a channel id (channelListingIds). Cannot be combined with listingIds. |
listingIds | string[] | Or the bookings of these properties (listingId). |
from | YYYY-MM-DD | Arrival from (inclusive). |
to | YYYY-MM-DD | Arrival to (inclusive). |
An empty body exports every booking in the account. The maximum is 3000 bookings per export; above that, the export fails with the reason in error and you need to split it by dates.
curl -X POST https://api.kinapi.es/api/v1/exports \
-H "ocp-apim-subscription-key: YOUR_API_KEY" \
-H "content-type: application/json" \
-d '{ "ownerId": "a1b2c3d4-…" }'It answers 202 at once with the export object in pending. The ZIP is generated in the background: each booking means several PDFs created on the spot.
{
"id": "3f6c1e2a-…",
"status": "pending",
"description": "Propietario Gestora Costa SL",
"scope": { "ownerId": "a1b2c3d4-…", "listingIds": null, "from": null, "to": null },
"requestedBy": "api",
"createdAt": "2026-10-14T09:00:00.000Z",
"finishedAt": null,
"expiresAt": null,
"bookings": null,
"files": null,
"bytes": null,
"error": null
}The export object
| Field | Type | Description |
|---|---|---|
id | string | Export id. |
status | string | pending, processing, ready, failed or expired (table below). |
description | string | What is exported, in Spanish: “Propietario Gestora Costa SL, llegadas del 01/01/2025 al 31/12/2025”. |
scope | object | { ownerId, listingIds, from, to } as requested; null for whatever was not filtered. |
requestedBy | string | The email of the panel user who requested it, or api. |
createdAt | ISO 8601 | When it was requested. |
finishedAt | ISO 8601 | null | When it finished, ready or failed. |
expiresAt | ISO 8601 | null | Until when the ZIP can be downloaded. |
bookings | integer | null | Bookings included, once ready. |
files | integer | null | Files inside the ZIP, once ready. |
bytes | integer | null | Size of the ZIP, once ready. |
error | string | null | Why it failed, in Spanish. |
| Field | Type | Description |
|---|---|---|
pending | status | Requested, queued. |
processing | status | Being generated. |
ready | status | Ready: download it from …/download until expiresAt. |
failed | status | It could not be generated; error says why. Request another one. |
expired | status | The ZIP was deleted seven days after it was ready. Request another one. |
Know when it is ready
No polling needed: when it finishes, Kinapi emits the export.ready or export.failed webhook (see Webhooks). If you do not use webhooks, check GET /exports/{id} every few minutes.
{
"event": "export.ready",
"timestamp": "2026-10-14T09:03:12.000Z",
"livemode": true,
"data": {
"exportId": "3f6c1e2a-…",
"description": "Propietario Gestora Costa SL",
"bookings": 412,
"bytes": 184503112,
"expiresAt": "2026-10-21T09:03:12.000Z"
}
}export.failed carries exportId, description and error.
List and read exports
/exportsThe account’s exports, most recent first (up to 50), in results. Each one is kept for 30 days; its ZIP, only seven.
/exports/{id}The export object, with its current status.
Download the ZIP
/exports/{id}/downloadcurl -OJ https://api.kinapi.es/api/v1/exports/3f6c1e2a-…/download \ -H "ocp-apim-subscription-key: YOUR_API_KEY"
| Field | Type | Description |
|---|---|---|
200 | application/zip | The ZIP, streamed, with content-disposition kinapi-registros-<date>-<id>.zip. |
409 not_ready | error | It is still being generated, or it failed (details carries the reason). |
410 expired | error | The ZIP has been deleted: it expires seven days after it is ready. Request a new export. |
404 | error | There is no export with that id in your account. |
What is in the ZIP
LEEME.txt
reservas.csv
huespedes.csv
comunicaciones-ses.csv
reservas/
2026-08-14_R-2026-0412/
reserva.json
partes/parte-1.pdf
partes/parte-2.pdf
justificante-ses.pdf
contrato.pdf
evidencia/<id>.json
evidencia/<id>.tsr| Field | Type | Description |
|---|---|---|
LEEME.txt | text | What the ZIP contains, how to verify a timestamp and how long to keep it (in Spanish). |
reservas.csv | csv | One row per booking: accommodation, establishment code, owner and their tax number, check-in, check-out, travellers, status, contract signing date and the folder holding its documents. |
huespedes.csv | csv | One row per traveller, with the report data. |
comunicaciones-ses.csv | csv | One row per traveller and submission to SES.HOSPEDAJES: batch, environment, date, result, communication code or error, and the annulment if there was one. |
reserva.json | json | The booking, its guests, its SES submissions and the signature evidence, exactly as the API returns them. |
partes/parte-N.pdf | Each traveller’s report, with their signature. This is the document that must be kept for three years and shown on request. | |
justificante-ses.pdf | The booking’s proof of filing (see SES Hospedajes), when something was filed. | |
contrato.pdf | The signed contract with its evidence page, when there is one. | |
evidencia/<id>.json · .tsr | json · tsr | For each signed contract, the evidence record and its RFC 3161 timestamp. |
Each booking has its folder under reservas/<arrival>_<reservationId>/. File and column names are in Spanish. The CSV files are semicolon-separated and carry a BOM, which is what Spanish Excel opens cleanly, and they are protected against formula injection: a cell starting with =, +, - or @ gets an apostrophe in front.
The timestamp can be verified without relying on Kinapi, with OpenSSL (more detail in Contracts):
cd reservas/2026-08-14_R-2026-0412 openssl ts -verify -digest $(shasum -a 256 contrato.pdf | cut -d' ' -f1) \ -in evidencia/EVIDENCE_ID.tsr -CAfile /etc/ssl/cert.pem
The ZIP contains travellers’ personal data. Store it with the safeguards the GDPR requires, hand it only to the owner, and delete it once its retention period is over.
From the panel
In Settings → Export data you pick the whole account or one owner, and optionally a range of arrivals; the page refreshes itself while the export is generated. In Owners, the download icon on each row opens that same page with the owner already selected. Panel and API exports are the same thing: they show up in both lists.
Offboard an owner
When you stop managing an owner, go to Owners and click Offboard this owner (the icon on their row). It is a panel assistant — there is no endpoint — with four steps. Each can be done on its own, but in this order:
- Cancel their upcoming bookings (arrival today or later). Otherwise Kinapi would keep inviting those guests and filing their reports. Cancelling annuls with the Ministry whatever had already been filed.
- Generate their export, to hand it over. It includes their deactivated properties.
- Deactivate their properties. Those with no booking at all are deleted; the rest keep their history.
- Suppress their data. Requires step 1 to be done and typing
SUPPRESS. The personal data of all their stays — guests, signatures, contracts and lead guest — is deleted, along with the owner record.
What the law requires to keep — the reports from the last three years — is not deleted in step 4: it is held blocked outside your account, with no access from the panel or the API, and deleted once its three years run out. The bookings stay listed, anonymised, so your lists and your billing still add up: the check-in then carries anonymizedAt and no longer has guests, a lead guest or files. A booking whose report is on its way to the Ministry is skipped and suppressed on a later attempt, once it has been confirmed.
Step 4 cannot be undone. Export first and make sure the owner has their copy.
Over the API you can prepare steps 1 and 2: GET /checkins?ownerId=…&from=YYYY-MM-DD lists their bookings (deactivated properties included), DELETE /checkins/{reservationId} cancels each one (or deletes it, if it left nothing worth keeping), and POST /exports with ownerId generates their ZIP.
Closing the account
It is requested in Settings → Account → Request the account closure, and only an admin can do it. The account closes at once and a 30-day grace period starts:
- No reports are filed with the Ministry.
- Guests receive no emails and their registration links stop working.
- The API answers
403 account_closingon every endpoint except/exports: you can keep pulling your records over the API. - The panel only shows the closure screen: reactivate the account with one click, or export the records.
{
"error": "account_closing",
"details": "La baja de la cuenta está pedida y se hará efectiva el 2026-11-13. Hasta entonces la API solo permite exportar los registros (/exports); para volver a usarla, reactiva la cuenta desde el panel.",
"effectiveAt": "2026-11-13T09:00:00.000Z"
}If you reactivate within those 30 days, everything works again with nothing lost. When they run out, the closure is carried out:
- The reports of stays from the last three years are kept blocked — no access for anyone, except on request from a competent authority — and deleted once their period runs out.
- Signed contracts and their timestamps remain for three years in the immutable storage where they were archived.
- Everything else is deleted.
Before requesting the closure, export the whole account (POST /exports with an empty body). You can also do it during the grace period, but after the final closure nobody will have access to those records — not you, not the owner.
What expires while the account is active
Kinapi never deletes traveller records on its own: reports, contracts and proofs of filing stay there for as long as you have the account. Only these expire:
| Field | Type | Description |
|---|---|---|
Guest registration link | 14 days | After the check-out date. It then answers 410; the data that was registered stays on the booking. |
Webhook delivery log | 30 days | The history of attempts you see in Settings → Webhooks. |
Export ZIP | 7 days | From when it is ready. The export record itself is listed for 30 days. |