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

POST/exports
Body (all optional)
FieldTypeDescription
ownerIdstringThe 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.
listingIdsstring[]Or the bookings of these properties (listingId).
fromYYYY-MM-DDArrival from (inclusive).
toYYYY-MM-DDArrival 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 — everything for one owner
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.

202 Accepted
{
  "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

Fields
FieldTypeDescription
idstringExport id.
statusstringpending, processing, ready, failed or expired (table below).
descriptionstringWhat is exported, in Spanish: “Propietario Gestora Costa SL, llegadas del 01/01/2025 al 31/12/2025”.
scopeobject{ ownerId, listingIds, from, to } as requested; null for whatever was not filtered.
requestedBystringThe email of the panel user who requested it, or api.
createdAtISO 8601When it was requested.
finishedAtISO 8601 | nullWhen it finished, ready or failed.
expiresAtISO 8601 | nullUntil when the ZIP can be downloaded.
bookingsinteger | nullBookings included, once ready.
filesinteger | nullFiles inside the ZIP, once ready.
bytesinteger | nullSize of the ZIP, once ready.
errorstring | nullWhy it failed, in Spanish.
Statuses (status)
FieldTypeDescription
pendingstatusRequested, queued.
processingstatusBeing generated.
readystatusReady: download it from …/download until expiresAt.
failedstatusIt could not be generated; error says why. Request another one.
expiredstatusThe 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.

POST to your URL — export.ready
{
  "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

GET/exports

The account’s exports, most recent first (up to 50), in results. Each one is kept for 30 days; its ZIP, only seven.

GET/exports/{id}

The export object, with its current status.

Download the ZIP

GET/exports/{id}/download
curl
curl -OJ https://api.kinapi.es/api/v1/exports/3f6c1e2a-…/download \
  -H "ocp-apim-subscription-key: YOUR_API_KEY"
Responses
FieldTypeDescription
200application/zipThe ZIP, streamed, with content-disposition kinapi-registros-<date>-<id>.zip.
409 not_readyerrorIt is still being generated, or it failed (details carries the reason).
410 expirederrorThe ZIP has been deleted: it expires seven days after it is ready. Request a new export.
404errorThere is no export with that id in your account.

What is in the ZIP

Layout
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
Files
FieldTypeDescription
LEEME.txttextWhat the ZIP contains, how to verify a timestamp and how long to keep it (in Spanish).
reservas.csvcsvOne 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.csvcsvOne row per traveller, with the report data.
comunicaciones-ses.csvcsvOne row per traveller and submission to SES.HOSPEDAJES: batch, environment, date, result, communication code or error, and the annulment if there was one.
reserva.jsonjsonThe booking, its guests, its SES submissions and the signature evidence, exactly as the API returns them.
partes/parte-N.pdfpdfEach traveller’s report, with their signature. This is the document that must be kept for three years and shown on request.
justificante-ses.pdfpdfThe booking’s proof of filing (see SES Hospedajes), when something was filed.
contrato.pdfpdfThe signed contract with its evidence page, when there is one.
evidencia/<id>.json · .tsrjson · tsrFor 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):

Verify a timestamp from the ZIP
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:

  1. 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.
  2. Generate their export, to hand it over. It includes their deactivated properties.
  3. Deactivate their properties. Those with no booking at all are deleted; the rest keep their history.
  4. 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_closing on 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.
403 Forbidden — closure requested
{
  "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:

FieldTypeDescription
Guest registration link14 daysAfter the check-out date. It then answers 410; the data that was registered stays on the booking.
Webhook delivery log30 daysThe history of attempts you see in Settings → Webhooks.
Export ZIP7 daysFrom when it is ready. The export record itself is listed for 30 days.