Data formats
What every file you can export from Staywick holds, column by column, and every field of the public API and its webhooks. The page is built from the code that writes the files, so it always describes the version running now.
Archive format staywick-export, version 1.
Four ways to take your data
- From the dashboard: the Bookings, Guests, Registration, Payments, Invoices, Owners and Analytics screens each export what they show — as CSV on every plan, and as Excel (XLSX) or a printable page on Standard and above (the guest register in every format on every plan). This works also while the account is locked.
- Export everything: the account owner downloads the whole organization as one ZIP file — every table, the owner statements, the analytics report, signed rental agreements, photos and the logo. Free on every plan, also while the account is locked, 3 times a day.
- One by one as PDF: invoices, booking confirmations and signed rental agreements.
- Through the public API, on Pro and above while the trial or subscription is active: units, bookings, availability and prices.
How the files are written
- CSV files are UTF-8 with a byte order mark, so spreadsheets show accented letters correctly. Values are separated by commas, one record per line.
- A value that holds a comma, a double quote or a line break is wrapped in double quotes, and a double quote inside it is doubled.
- The first line of each CSV names its columns, in the order listed on this page.
- A text value that begins with =, +, -, @, a tab or a carriage return is written with an apostrophe in front of it in the CSV, so a spreadsheet never runs it as a formula. The JSON file keeps the value unchanged.
- An empty CSV cell, and null in JSON, means there is no value.
- Yes/no values are written true or false.
- JSON values and lists are JSON text inside a CSV cell, and real JSON in the .json file.
- Each .json file is one array of records with the same field names as the CSV's columns. It is complete, and it is the file to use when moving to another system.
- Dates are written YYYY-MM-DD, and times of day HH:MM or HH:MM:SS.
- A date with a time is ISO 8601 in UTC, for example 2026-07-02T09:14:00+00:00, sometimes with fractions of a second.
- Amounts are numbers with a dot as the decimal mark, in the property's currency (property.currency in manifest.json). The API writes amounts as text instead, such as "120.00".
- Every id is a UUID that never changes: the same record has the same id in every export and in the API, and a column that points to another file holds that file's id.
- Column and field names are in English and the same in every language. What was typed — unit names, notes, messages — is as it was typed. The headings of the owner statements and of the analytics report are in the language of whoever exported them.
- Rows are read page by page while the account keeps working, between startedAt and finishedAt in manifest.json, so the archive is not a snapshot of one instant.
- The archive is a standard ZIP without ZIP64, so it holds at most 4,294,967,294 bytes and 65,534 files. When an export would come near that — above 3,900,000,000 bytes or 65,000 files — the photos are left out, and everything else still fits.
- The account owner can run the full export 3 times in any 24 hours. Each screen's own export always works.
- Photos and the logo are the files as they are stored, which were made smaller when they were uploaded.
The full export (ZIP)
README.txtWhat the archive holds, in the language of whoever exported it, with the address of this page.
manifest.jsonWhat is in the archive, how many rows each file holds, what was left out and why. Its fields are listed below.
data/<part>.csvdata/<part>.jsonOne table each, as CSV and as JSON. Every file and its columns are described below.
owner-statements/<owner>.csvowner-statements/<owner>.jsonEach owner's statements, month by month, as on the Owners screen.
reports/analytics-365-days.csvreports/analytics-365-days.jsonThe analytics report for the last 365 days, when the plan includes analytics.
agreements/<confirmation_number>.pdfEach signed rental agreement as a PDF, named by its booking's number.
photos/property/cover-<file>photos/property/<NN>-<file>The listing's cover and its photos, numbered in their order.
photos/units/<unit>/<NN>-<file>Each unit's photos, numbered in their order.
photos/unused/<file>Files still in storage that no listing uses any more.
photos/index.csvWhere each downloaded photo is used.
zip_pathtext
used_asvalue from a list
one of:
logo,cover,property,unit,unusedunittext
may be empty
positionwhole number
may be empty
source_urltext
byteswhole number
may be empty
statusvalue from a list
one of:
ok,missing,not_included
photos/external-links.csvPictures linked from other websites: listed, never downloaded.
used_asvalue from a list
one of:
logo,cover,property,unit,unusedunittext
may be empty
positionwhole number
may be empty
urltext
branding/logo.<ext>The logo, if one was uploaded.
Fields of manifest.json
formatThe format's name: staywick-export.versionThe format's version.documentationThe address of this page.propertyThe property's id, name, currency and time zone.startedAtWhen the export started (UTC).finishedAtWhen it finished (UTC).consistencyHow the rows were read: page by page, between the two times.partsFor each part written: its files and how many rows it holds.skippedEach part that was left out, and why.photosWhether the photos are included, how many files and bytes, which could not be downloaded, and how many are linked from elsewhere or unused.agreementsHow many agreement PDFs were written, and which could not be.notExportedThe internal tables that never leave.zipLimitsThe ZIP limits described above.
Why a part is listed in skipped
missingTableThe database did not have that table yet.missingColumnThe database did not have one of its columns yet.notOnPlanThe plan does not include it.failedThe server or the network refused it, after a second try.notIncludedThe owner chose to leave it out (the photos).
Every file and its columns
Each table is written twice with the same columns: as data/<part>.csv and as data/<part>.json. The columns are listed in their order, each with its type and the database's own type beside it.
01Units, with their settings, photos, calendars, prices, pricing rules and offers
data/units.csvdata/units.json
Each unit — apartment, room or house: its name, settings, check-in details, door code and Wi-Fi, and its photo addresses.Columns: 32
data/units.csvdata/units.jsonidid (UUID)
uuidnumbertext
character varying(120)The unit's name, as the host wrote it.
room_type_idid (UUID)
uuidmay be empty · points to
unit-types.idsort_orderwhole number
integermay be empty
statusvalue from a list
room_statusone of:
available,occupied,dirty,inspected,maintenance,dnd,out_of_orderfloorwhole number
integermay be empty
is_smokingtrue/false
booleandescriptiontext
textmay be empty
amenitiesJSON
jsonbmay be empty
photosJSON
jsonbmay be empty
The unit's photo addresses, in order.
addresstext
textmay be empty
citytext
character varying(100)may be empty
countrytext
character varying(100)may be empty
latdecimal number
numeric(10,7)may be empty
lngdecimal number
numeric(10,7)may be empty
max_occupancywhole number
integermay be empty
base_pricedecimal number
numeric(10,2)may be empty
The price per night when no other price applies.
price_mindecimal number
numeric(10,2)may be empty
price_maxdecimal number
numeric(10,2)may be empty
min_nightswhole number
integermay be empty
check_in_timetext
character varying(5)may be empty
HH:MM; empty means the property's time.
check_out_timetext
character varying(5)may be empty
check_in_instructionstext
textmay be empty
access_codetext
character varying(50)may be empty
The door code. Keep the file safe.
wifi_nametext
character varying(100)may be empty
wifi_passwordtext
character varying(100)may be empty
online_checkintrue/false
booleanmay be empty
code_after_checkintrue/false
booleanmay be empty
default_cleaner_idid (UUID)
uuidmay be empty · points to
team.idnotestext
textmay be empty
created_atdate and time (UTC)
timestamp with time zoneupdated_atdate and time (UTC)
timestamp with time zone
Columns of this table that are not exported: 1 (credentials and private links).
data/unit-types.csvdata/unit-types.json
Unit types: settings and prices that units can share.Columns: 10
data/unit-types.csvdata/unit-types.jsonidid (UUID)
uuidnametext
character varying(100)descriptiontext
textmay be empty
base_pricedecimal number
numeric(10,2)max_occupancywhole number
integerbed_typetext
character varying(50)size_sqftwhole number
integermay be empty
amenitiesJSON
jsonbmay be empty
imagesJSON
jsonbmay be empty
created_atdate and time (UTC)
timestamp with time zone
data/unit-calendar.csvdata/unit-calendar.json
Per-night prices and the nights the host closed, one row per unit and night.Columns: 8
data/unit-calendar.csvdata/unit-calendar.jsonidid (UUID)
uuidroom_idid (UUID)
uuidpoints to
units.iddatedate
datepricedecimal number
numeric(10,2)may be empty
That night's own price; empty means the unit's price.
blockedtrue/false
booleannotetext
textmay be empty
created_atdate and time (UTC)
timestamp with time zoneupdated_atdate and time (UTC)
timestamp with time zone
data/pricing-rules.csvdata/pricing-rules.json
Pricing rules and offers: seasons, days of the week, and discounts for longer, early or last-minute stays.Columns: 13
data/pricing-rules.csvdata/pricing-rules.jsonidid (UUID)
uuidkindtext
textseason, weekend, length_of_stay, early_bird or last_minute.
nametext
character varying(80)percentdecimal number
numeric(5,2)For season and weekend, the change in percent (negative lowers the price); for the others, the discount in percent.
date_fromdate
datemay be empty
date_todate
datemay be empty
weekdayslist of: whole number
smallint[]may be empty
The days of the week it applies to: 1 = Monday … 7 = Sunday.
min_nightswhole number
integermay be empty
days_beforewhole number
integermay be empty
unit_idslist of: id (UUID)
uuid[]may be empty · points to
units.idThe units it applies to; empty means every unit.
activetrue/false
booleancreated_atdate and time (UTC)
timestamp with time zoneupdated_atdate and time (UTC)
timestamp with time zone
data/unit-compliance.csvdata/unit-compliance.json
A unit's own guest-register and tourist-tax settings, where they differ from the property's.Columns: 10
data/unit-compliance.csvdata/unit-compliance.jsonroom_idid (UUID)
uuidpoints to
units.idregistertext
character varying(20)may be empty
tourist_tax_ratedecimal number
numeric(10,2)may be empty
free_under_agewhole number
integermay be empty
half_under_agewhole number
integermay be empty
obligor_nametext
character varying(200)may be empty
obligor_tax_idtext
character varying(50)may be empty
facility_codetext
character varying(50)may be empty
created_atdate and time (UTC)
timestamp with time zoneupdated_atdate and time (UTC)
timestamp with time zone
data/calendar-feeds.csvdata/calendar-feeds.json
Calendars imported from other channels (iCal links).Columns: 7
data/calendar-feeds.csvdata/calendar-feeds.jsonidid (UUID)
uuidroom_idid (UUID)
uuidpoints to
units.idsourcetext
character varying(100)channel_idtext
character varying(40)may be empty
urltext
textlast_synced_atdate and time (UTC)
timestamp with time zonemay be empty
created_atdate and time (UTC)
timestamp with time zone
data/imported-calendar.csvdata/imported-calendar.json
The stays and blocks read from those calendars.Columns: 11
data/imported-calendar.csvdata/imported-calendar.jsonidid (UUID)
uuidroom_idid (UUID)
uuidpoints to
units.idfeed_idid (UUID)
uuidpoints to
calendar-feeds.idsourcetext
character varying(100)may be empty
uidtext
textstart_datedate
dateend_datedate
dateThe day the stay ends; that night is free.
summarytext
textmay be empty
channel_reftext
character varying(40)may be empty
phone_hinttext
character varying(4)may be empty
created_atdate and time (UTC)
timestamp with time zone
data/channels.csvdata/channels.json
Channel connections and their state.Columns: 7
data/channels.csvdata/channels.jsonidid (UUID)
uuidchannel_idtext
character varying(40)modetext
character varying(10)statustext
character varying(24)last_errortext
textmay be empty
created_atdate and time (UTC)
timestamp with time zoneupdated_atdate and time (UTC)
timestamp with time zone
Columns of this table that are not exported: 2 (credentials and private links).
02Bookings and booking requests, with their payment entries
data/bookings.csvdata/bookings.json
Every booking and booking request, with its dates, guest, price and channel. A booking confirmation is this record.Columns: 30
data/bookings.csvdata/bookings.jsonidid (UUID)
uuidconfirmation_numbertext
character varying(20)statusvalue from a list
reservation_statusone of:
tentative,confirmed,checked_in,checked_out,cancelled,no_showguest_idid (UUID)
uuidmay be empty · points to
guests.idroom_idid (UUID)
uuidmay be empty · points to
units.idroom_type_idid (UUID)
uuidmay be empty · points to
unit-types.idcheck_in_datedate
datecheck_out_datedate
dateThe day the guest leaves; that night is not part of the stay.
actual_check_indate and time (UTC)
timestamp with time zonemay be empty
actual_check_outdate and time (UTC)
timestamp with time zonemay be empty
adultswhole number
integerchildrenwhole number
integerrate_planvalue from a list
rate_plan_typeone of:
bar,package,corporate,government,promotionalrate_per_nightdecimal number
numeric(10,2)total_amountdecimal number
numeric(10,2)The stay's total, after any discount.
discount_amountdecimal number
numeric(10,2)may be empty
discount_detailJSON
jsonbmay be empty
How the discount was worked out.
payment_due_atdate and time (UTC)
timestamp with time zonemay be empty
payment_due_amountdecimal number
numeric(10,2)may be empty
billingJSON
jsonbmay be empty
The invoice details the guest gave at online check-in: company, tax number, address.
channelvalue from a list
channelone of:
direct,booking_com,expedia,airbnb,hotels_com,gds,phone,walk_inchannel_confirmation_idtext
character varying(100)may be empty
group_idid (UUID)
uuidmay be empty
corporate_account_idid (UUID)
uuidmay be empty
special_requeststext
textmay be empty
early_check_intrue/false
booleanlate_check_outtrue/false
booleanlocaletext
textmay be empty
The language of the guest's e-mails.
created_atdate and time (UTC)
timestamp with time zoneupdated_atdate and time (UTC)
timestamp with time zone
Columns of this table that are not exported: 2 (credentials and private links).
data/payments-and-expenses.csvdata/payments-and-expenses.json
Payments received and expenses, as on the Payments screen.Columns: 11
data/payments-and-expenses.csvdata/payments-and-expenses.jsonidid (UUID)
uuidtypevalue from a list
ledger_typeone of:
income,expensecategorytext
character varying(60)descriptiontext
textmay be empty
amountdecimal number
numeric(12,2)Always positive; type says whether it is income or an expense.
currencytext
character varying(3)methodtext
character varying(30)may be empty
entry_datedate
datereservation_idid (UUID)
uuidmay be empty · points to
bookings.idroom_idid (UUID)
uuidmay be empty · points to
units.idcreated_atdate and time (UTC)
timestamp with time zone
03Guests and the guest register
data/guests.csvdata/guests.json
The guest book: each guest's contact details and what is known about them.Columns: 22
data/guests.csvdata/guests.jsonidid (UUID)
uuidfirst_nametext
character varying(100)last_nametext
character varying(100)emailtext
character varying(255)may be empty
phonetext
character varying(50)may be empty
nationalitytext
character varying(100)may be empty
passport_numbertext
character varying(50)may be empty
date_of_birthdate
datemay be empty
addressJSON
jsonbmay be empty
notestext
textmay be empty
tagslist of: text
text[]may be empty
preferencesJSON
jsonbmay be empty
dietary_restrictionslist of: text
text[]may be empty
loyalty_tiervalue from a list
loyalty_tiermay be empty
one of:
bronze,silver,gold,platinum,invite_onlyloyalty_pointswhole number
integerlifetime_valuedecimal number
numeric(12,2)total_stayswhole number
integermarketing_consenttrue/false
booleangdpr_consenttrue/false
booleangdpr_consent_datedate and time (UTC)
timestamp with time zonemay be empty
created_atdate and time (UTC)
timestamp with time zoneupdated_atdate and time (UTC)
timestamp with time zone
data/guest-register.csvdata/guest-register.json
Everyone registered for a stay, with their identity document details.Columns: 15
data/guest-register.csvdata/guest-register.jsonidid (UUID)
uuidreservation_idid (UUID)
uuidpoints to
bookings.idis_leadtrue/false
booleantrue for the guest who made the booking.
first_nametext
character varying(100)last_nametext
character varying(100)date_of_birthdate
datemay be empty
nationalitytext
character varying(100)may be empty
document_typetext
character varying(20)document_numbertext
character varying(50)may be empty
gendertext
character varying(10)may be empty
self_registered_atdate and time (UTC)
timestamp with time zonemay be empty
created_atdate and time (UTC)
timestamp with time zoneupdated_atdate and time (UTC)
timestamp with time zoneage_at_arrivalwhole number
smallintmay be empty
Age on the day of arrival, kept when the date of birth is removed.
details_removed_atdate and time (UTC)
timestamp with time zonemay be empty
When the identity details were removed, after the period set for the register.
data/registrations.csvdata/registrations.json
Each stay's registration with the authorities, and its tourist tax.Columns: 8
data/registrations.csvdata/registrations.jsonreservation_idid (UUID)
uuidpoints to
bookings.idstatustext
character varying(20)pending, exported or filed.
tourist_tax_amountdecimal number
numeric(10,2)may be empty
exported_atdate and time (UTC)
timestamp with time zonemay be empty
filed_atdate and time (UTC)
timestamp with time zonemay be empty
referencetext
character varying(100)may be empty
created_atdate and time (UTC)
timestamp with time zoneupdated_atdate and time (UTC)
timestamp with time zone
data/compliance-settings.csvdata/compliance-settings.json
The property's guest-register and tourist-tax settings.Columns: 10
data/compliance-settings.csvdata/compliance-settings.jsonregistertext
character varying(20)tourist_tax_ratedecimal number
numeric(10,2)free_under_agewhole number
integerhalf_under_agewhole number
integerobligor_nametext
character varying(200)may be empty
obligor_tax_idtext
character varying(50)may be empty
facility_codetext
character varying(50)may be empty
created_atdate and time (UTC)
timestamp with time zoneupdated_atdate and time (UTC)
timestamp with time zoneregister_retention_monthswhole number
smallintmay be empty
04Invoices and booking confirmations
data/invoices.csvdata/invoices.json
Invoices and credit notes, with their lines and totals.Columns: 26
data/invoices.csvdata/invoices.jsonidid (UUID)
uuidnumbertext
textmay be empty
kindtext
textinvoice or credit_note.
statustext
textdraft, issued, sent, paid or cancelled.
yearwhole number
integermay be empty
seqwhole number
integermay be empty
reservation_idid (UUID)
uuidmay be empty · points to
bookings.idcredit_ofissued_atdate
datemay be empty
due_atdate
datemay be empty
currencytext
character varying(3)localetext
textmay be empty
recipientJSON
jsonbWho the invoice is made out to.
itemsJSON
jsonbThe invoice's lines.
net_totaldecimal number
numeric(12,2)tax_totaldecimal number
numeric(12,2)totaldecimal number
numeric(12,2)payment_methodtext
texttermstext
textnotetext
textautotrue/false
booleansent_atdate and time (UTC)
timestamp with time zonemay be empty
paid_atdate and time (UTC)
timestamp with time zonemay be empty
cancelled_atdate and time (UTC)
timestamp with time zonemay be empty
created_atdate and time (UTC)
timestamp with time zoneupdated_atdate and time (UTC)
timestamp with time zone
data/invoice-settings.csvdata/invoice-settings.json
What every invoice says about the issuer: legal name, address, tax number, bank account and numbering.Columns: 11
data/invoice-settings.csvdata/invoice-settings.jsonlegal_nametext
textaddresstext
texttax_idtext
textibantext
textnumber_prefixtext
textdue_dayswhole number
integersecond_currencytext
character varying(3)may be empty
notetext
texttermstext
textcreated_atdate and time (UTC)
timestamp with time zoneupdated_atdate and time (UTC)
timestamp with time zone
data/invoice-counters.csvdata/invoice-counters.json
The last invoice number used in each year.Columns: 2
data/invoice-counters.csvdata/invoice-counters.jsonyearwhole number
integerlast_seqwhole number
integer
05Messages, inbox conversations and saved replies
data/inbox.csvdata/inbox.json
Inbox messages to and from guests.Columns: 8
data/inbox.csvdata/inbox.jsonidid (UUID)
uuidreservation_idid (UUID)
uuidmay be empty · points to
bookings.idguest_idid (UUID)
uuidmay be empty · points to
guests.iddirectiontext
character varying(10)inbound from the guest, outbound to the guest.
channeltext
character varying(20)statustext
character varying(20)bodytext
textcreated_atdate and time (UTC)
timestamp with time zone
data/guest-mail.csvdata/guest-mail.json
The automatic e-mails to guests: their text, and when they were sent.Columns: 13
data/guest-mail.csvdata/guest-mail.jsonidid (UUID)
uuidreservation_idid (UUID)
uuidmay be empty · points to
bookings.idguest_idid (UUID)
uuidmay be empty · points to
guests.idkindvalue from a list
message_kindone of:
booking_confirmation,pre_arrival,post_stay,cancellation,booking_request,checkin_reminderchanneltext
character varying(20)to_emailtext
character varying(255)may be empty
subjecttext
textmay be empty
bodytext
textmay be empty
statusvalue from a list
message_statusone of:
ready,sent,failed,skippederrortext
textmay be empty
scheduled_fordate
datemay be empty
sent_atdate and time (UTC)
timestamp with time zonemay be empty
created_atdate and time (UTC)
timestamp with time zone
data/saved-replies.csvdata/saved-replies.json
Saved replies.Columns: 6
data/saved-replies.csvdata/saved-replies.jsonidid (UUID)
uuidtitletext
character varying(80)bodytext
textsort_orderwhole number
integercreated_atdate and time (UTC)
timestamp with time zoneupdated_atdate and time (UTC)
timestamp with time zone
data/message-templates.csvdata/message-templates.json
The templates of the automatic messages, and when each is sent.Columns: 8
data/message-templates.csvdata/message-templates.jsonidid (UUID)
uuidkindvalue from a list
message_kindone of:
booking_confirmation,pre_arrival,post_stay,cancellation,booking_request,checkin_reminderenabledtrue/false
booleanlead_dayswhole number
integersubjecttext
textbodytext
textcreated_atdate and time (UTC)
timestamp with time zoneupdated_atdate and time (UTC)
timestamp with time zone
06Reviews
data/reviews.csvdata/reviews.json
The reviews guests left after their stay.Columns: 7
data/reviews.csvdata/reviews.jsonidid (UUID)
uuidreservation_idid (UUID)
uuidpoints to
bookings.idguest_idid (UUID)
uuidmay be empty · points to
guests.idratingwhole number
smallintcommenttext
textmay be empty
localetext
character varying(8)may be empty
created_atdate and time (UTC)
timestamp with time zone
07Cleaning tasks
data/cleaning-tasks.csvdata/cleaning-tasks.json
Cleaning tasks, with their checklist and who does them.Columns: 14
data/cleaning-tasks.csvdata/cleaning-tasks.jsonidid (UUID)
uuidroom_idid (UUID)
uuidpoints to
units.idreservation_idid (UUID)
uuidmay be empty · points to
bookings.idtypevalue from a list
housekeeping_typeone of:
standard,deep,turndown,inspect,restockstatusvalue from a list
housekeeping_statusone of:
pending,in_progress,inspected,confirmedpriorityvalue from a list
task_priorityone of:
low,normal,high,urgentscheduled_datedate
datemay be empty
assigned_toid (UUID)
uuidmay be empty · points to
team.idassign_modetext
character varying(10)may be empty
notestext
textmay be empty
checklistJSON
jsonbmay be empty
completed_atdate and time (UTC)
timestamp with time zonemay be empty
created_atdate and time (UTC)
timestamp with time zoneupdated_atdate and time (UTC)
timestamp with time zone
08Property owners and owner statements
data/owners.csvdata/owners.json
Property owners, with their contact and bank details and their commission.Columns: 10
data/owners.csvdata/owners.jsonidid (UUID)
uuidnametext
character varying(200)emailtext
character varying(255)may be empty
phonetext
character varying(50)may be empty
ibantext
character varying(50)may be empty
commission_pctdecimal number
numeric(5,2)notestext
textmay be empty
is_activetrue/false
booleancreated_atdate and time (UTC)
timestamp with time zoneupdated_atdate and time (UTC)
timestamp with time zone
data/owner-units.csvdata/owner-units.json
Which owner owns which unit.Columns: 3
data/owner-units.csvdata/owner-units.jsonowner-statements/<owner>.csvowner-statements/<owner>.json
Each owner's statements, month by month: revenue, commission, expenses and payout, with the bookings and expenses behind them.Fields: 23
owner-statements/<owner>.csvowner-statements/<owner>.jsonowner-statements/<owner>.jsonownertext
monthslist of: object
months[]monthtext
YYYY-MM. A stay counts in the month it checks out.
revenuedecimal number
commissionPctdecimal number
commissiondecimal number
expensesdecimal number
payoutdecimal number
Revenue minus commission and expenses; it may be negative.
nightswhole number
bookingslist of: object
expenseLineslist of: object
bookings[]confirmationtext
unittext
guesttext
checkIndate
checkOutdate
nightswhole number
revenuedecimal number
expenseLines[]datedate
categorytext
descriptiontext
may be empty
unittext
amountdecimal number
09Team members' profiles
data/team.csvdata/team.json
Team members' profiles.Columns: 10
data/team.csvdata/team.jsonidid (UUID)
uuidfirst_nametext
character varying(100)last_nametext
character varying(100)emailtext
character varying(255)phonetext
character varying(50)may be empty
rolevalue from a list
staff_roleone of:
front_desk,housekeeping,maintenance,manager,admin,revenuedepartmenttext
character varying(100)may be empty
is_activetrue/false
booleanhire_datedate
datemay be empty
created_atdate and time (UTC)
timestamp with time zone
Columns of this table that are not exported: 3 (our own records of the account and unused fields).
10Signed rental agreements
data/agreements.csvdata/agreements.json
Each signed rental agreement: the text the guest signed, its SHA-256 fingerprint, and when and from where it was signed.Columns: 9
data/agreements.csvdata/agreements.jsonreservation_idid (UUID)
uuidpoints to
bookings.idsigner_nametext
character varying(200)signed_atdate and time (UTC)
timestamp with time zonelocaletext
character varying(10)bodyJSON
jsonbThe agreement exactly as the guest signed it.
body_sha256text
character(64)SHA-256 of the signed text, to show it has not changed.
iptext
character varying(64)may be empty
user_agenttext
character varying(400)may be empty
created_atdate and time (UTC)
timestamp with time zone
11Your organization's settings, booking page and branding
data/property.csvdata/property.json
The organization's settings: booking-page content, payment and check-in options, messaging and branding. One row.Columns: 56
data/property.csvdata/property.jsonidid (UUID)
uuidnametext
character varying(255)addresstext
textcitytext
character varying(100)countrytext
character varying(100)phonetext
character varying(50)may be empty
emailtext
character varying(255)may be empty
websitetext
character varying(255)may be empty
timezonetext
character varying(50)currencytext
character varying(3)date_formattext
textmay be empty
host_localetext
textmay be empty
check_in_timetext
character varying(5)check_out_timetext
character varying(5)tax_ratedecimal number
numeric(5,2)descriptiontext
textmay be empty
amenitiesJSON
jsonbcover_image_urltext
textmay be empty
photosJSON
jsonbThe listing's photo addresses, in order.
logo_urltext
textmay be empty
accent_colortext
character varying(9)may be empty
themetext
textmay be empty
public_slugtext
character varying(60)may be empty
direct_booking_enabledtrue/false
booleanhouse_rulestext
textcancellation_termstext
textpayment_methodstext
textpayment_policytext
textpayment_modetext
textpayment_deposit_pctwhole number
integerpayment_hold_minuteswhole number
integerpayment_instructionstext
textmay be empty
payment_bank_holdertext
textmay be empty
payment_bank_accounttext
textmay be empty
payment_bank_nametext
textmay be empty
payment_bank_swifttext
textmay be empty
online_checkintrue/false
booleanmrz_scantrue/false
booleancode_after_checkintrue/false
booleanrental_agreementtrue/false
booleanagreement_termstext
textauto_reply_enabledtrue/false
booleanauto_reply_fromtime of day
time without time zoneauto_reply_totime of day
time without time zoneauto_reply_bodytext
textmay be empty
whatsapp_numbertext
character varying(40)may be empty
messenger_pagetext
character varying(160)may be empty
viber_numbertext
character varying(40)may be empty
instagram_handletext
character varying(160)may be empty
telegram_handletext
character varying(160)may be empty
morning_brieftrue/false
booleancreated_atdate and time (UTC)
timestamp with time zoneupdated_atdate and time (UTC)
timestamp with time zonerequest_expiry_ontrue/false
booleanrequest_expiry_hourswhole number
integerrequest_expiry_sincedate and time (UTC)
timestamp with time zonemay be empty
Columns of this table that are not exported: 23 (credentials and private links, billing and plan records, and our own records of the account).
data/api-keys.csvdata/api-keys.json
API keys, by name and prefix. The keys themselves are never stored.Columns: 7
data/api-keys.csvdata/api-keys.jsonidid (UUID)
uuidnametext
character varying(80)prefixtext
character varying(20)The key's first characters, to tell keys apart; the key itself is never stored.
scopeslist of: text
text[]created_atdate and time (UTC)
timestamp with time zonelast_used_atdate and time (UTC)
timestamp with time zonemay be empty
revoked_atdate and time (UTC)
timestamp with time zonemay be empty
Columns of this table that are not exported: 2 (credentials and private links and our own records of the account).
data/webhooks.csvdata/webhooks.json
Webhook endpoints and the events each one receives.Columns: 8
data/webhooks.csvdata/webhooks.jsonidid (UUID)
uuidurltext
texteventslist of: text
text[]activetrue/false
booleanlast_delivery_atdate and time (UTC)
timestamp with time zonemay be empty
last_statuswhole number
integermay be empty
failureswhole number
integercreated_atdate and time (UTC)
timestamp with time zone
Columns of this table that are not exported: 1 (credentials and private links).
12Analytics reports
reports/analytics-365-days.csvreports/analytics-365-days.json
The analytics report for the last 365 days: a summary, then months, channels and units.Fields: 4
reports/analytics-365-days.csvreports/analytics-365-days.jsonreports/analytics-365-days.jsontitletext
columnslist of: text
rowslist of: list
One list of cells per row.
morelist of: object
may be empty
The further sections — months, channels and units — each with its own title, columns and rows.
Exports from each screen
Each screen's Export button gives its list as it is shown, with headings in the language of whoever exports it. These files are for reading and for an accountant; to move to another system, use the full export.
- Bookings: The bookings in the list: number, guest and contact, unit, dates and nights, status, channel, guests, amount and the day it was booked.
- Guests: The guest book: name, contact, nationality, loyalty, stays, total spent and the day each guest was added.
- Registration: One month's guest register: each person's stay, identity document and tourist tax, and who files it.
- Payments: The month's payments and expenses, the guests' payments, and the month's totals.
- Invoices: Issued invoices: number, dates, recipient, stay, net amount, tax, total, currency and status.
- Owners: One owner's statement for one month: the bookings, the expenses and the summary.
- Analytics: The analytics report for the chosen period: a summary, then months, channels and units.
What is never exported
Never exported: our security logs, rate-limit records and internal operational records, and credentials — keys, signing secrets, private links and the booking-delete code.
Public API
The API lets a channel manager, a website or other software read and change one property's units, bookings, availability and prices. It is part of Pro and above and answers only while the trial or subscription is active: the plan is checked on every request.
Create a key in Settings → API and webhooks. It begins with sw_live_ and is shown once: only its SHA-256 is stored, so a lost key cannot be recovered — revoke it and create another. Send it with every request as Authorization: Bearer <key>.
https://staywick.com/api/v1
Authorization: Bearer sw_live_…Every key can read. A key with the write scope can also create and cancel bookings and set prices and closed nights.
Each key may make 120 requests a minute; above that the answer is 429.
Requests and answers are JSON. Dates are YYYY-MM-DD, times ISO 8601 in UTC, and amounts are text with two decimals, such as "120.00", so no total is rounded. Everything is limited to the key's property: an id from another property answers 404. Answers are never cached.
Errors
Every failure has the same body. The message, in English, says what was wrong.
401 unauthorizedNo key, an unknown key or a revoked one.403 forbiddenThe key does not have the scope, or the plan does not include the API.404 not_foundNo such booking or unit in this property.409 conflictThe nights are taken or closed, or the contact details belong to another guest.422 invalid_requestThe query or the body is not valid; the message says why.429 rate_limitedToo many requests in a minute.500 server_errorSomething failed on our side.
{
"error": {
"code": "forbidden",
"message": "This key does not have the `write` scope."
}
}Objects
bookingidid (UUID)
confirmationNumbertext
may be empty
unitIdid (UUID)
may be empty
unitNametext
may be empty
arrivaldate
may be empty
departuredate
may be empty
The day the guest leaves; that night is not part of the stay.
nightswhole number
may be empty
statusvalue from a list
may be empty
one of:
tentative,confirmed,checked_in,checked_out,cancelled,no_showguestNametext
may be empty
null for a stay with no guest, such as a block or an import.
guestEmailtext
may be empty
guestPhonetext
may be empty
adultswhole number
may be empty
childrenwhole number
may be empty
totaldecimal number
may be empty
The stay's total, as text with two decimals.
currencytext
may be empty
channelvalue from a list
may be empty
one of:
direct,booking_com,expedia,airbnb,hotels_com,gds,phone,walk_increatedAtdate and time (UTC)
may be empty
updatedAtdate and time (UTC)
may be empty
unitidid (UUID)
nametext
The unit's name, as the host wrote it.
maxGuestswhole number
may be empty
minNightswhole number
may be empty
basePricedecimal number
may be empty
The unit type's price when the unit has none of its own.
currencytext
may be empty
nightdatedate
availabletrue/false
reasonvalue from a list
may be empty
one of:
booked,blockedbooked or blocked; null when the night is free.
rateunitIdid (UUID)
datedate
pricedecimal number
may be empty
In GET /api/v1/rates, what the night costs, with the pricing rules applied. In rates.updated, the price before the rules (see Webhooks).
blockedtrue/false
true when the host closed the night.
Endpoints
GET /api/v1/units
Key scope: read
Every unit of the property. basePrice falls back to the unit type's price, as on the booking page.
Answer · 200
{
"units": [
{
"id": "6c1f2a9e-3b4d-4e5f-8a6b-7c8d9e0f1a2b",
"name": "Apartment 3",
"maxGuests": 4,
"minNights": 2,
"basePrice": "80.00",
"currency": "EUR"
}
]
}GET /api/v1/bookings
Key scope: read
Stays that overlap from–to, latest arrival first. status takes a comma-separated list; limit is at most 500 (default 100); offset pages on.
Query parameters
fromdate
todate
statuslist of: value from a list
one of:
tentative,confirmed,checked_in,checked_out,cancelled,no_showComma-separated.
limitwhole number
default:
100offsetwhole number
default:
0
Answer · 200
{
"bookings": [
{
"id": "b3a91c08-6d24-4e57-a0b1-c2d3e4f5a6b7",
"confirmationNumber": "AP-7KQ2ZX",
"unitId": "6c1f2a9e-3b4d-4e5f-8a6b-7c8d9e0f1a2b",
"unitName": "Apartment 3",
"arrival": "2026-08-01",
"departure": "2026-08-05",
"nights": 4,
"status": "confirmed",
"guestName": "Jana Marić",
"guestEmail": "jana@example.com",
"guestPhone": "+38765123456",
"adults": 2,
"children": 1,
"total": "420.00",
"currency": "EUR",
"channel": "booking_com",
"createdAt": "2026-07-02T09:14:00Z",
"updatedAt": "2026-07-02T09:14:00Z"
}
],
"limit": 100,
"offset": 0
}GET /api/v1/bookings/{id}
Key scope: read
One stay, or 404.
Answer · 200
{
"booking": {
"id": "b3a91c08-6d24-4e57-a0b1-c2d3e4f5a6b7",
"confirmationNumber": "AP-7KQ2ZX",
"unitId": "6c1f2a9e-3b4d-4e5f-8a6b-7c8d9e0f1a2b",
"unitName": "Apartment 3",
"arrival": "2026-08-01",
"departure": "2026-08-05",
"nights": 4,
"status": "confirmed",
"guestName": "Jana Marić",
"guestEmail": "jana@example.com",
"guestPhone": "+38765123456",
"adults": 2,
"children": 1,
"total": "420.00",
"currency": "EUR",
"channel": "booking_com",
"createdAt": "2026-07-02T09:14:00Z",
"updatedAt": "2026-07-02T09:14:00Z"
}
}POST /api/v1/bookings
Key scope: write
Creates a stay and answers 201 with it. Staywick works out the price, as on the booking page; it cannot be sent. Without guest the stay is a block that holds the nights. Nights already taken or closed answer 409, and so does an e-mail address or phone number that belongs to another guest. A stay is at most 180 nights and starts at most 730 days ahead; past stays may be imported.
Body
unitIdid (UUID)
required
arrivaldate
required
departuredate
required
adultswhole number
default:
1childrenwhole number
default:
0statusvalue from a list
default:
confirmedone of:
tentative,confirmedchannelvalue from a list
default:
directone of:
direct,booking_com,expedia,airbnb,hotels_com,gds,phone,walk_innotetext
at most 2,000 characters
Stored as the booking's special requests.
localevalue from a list
one of:
en,hr,bs,sr,me,tr,de,it,es,el,pl,huThe language of the guest's e-mails. Left out, the phone number's country code decides.
guestobject
may be empty
Leave it out for a block without a guest.
guest.firstNametext
required
guest.lastNametext
guest.emailtext
guest.phonetext
Request
{
"unitId": "6c1f2a9e-3b4d-4e5f-8a6b-7c8d9e0f1a2b",
"arrival": "2026-08-01",
"departure": "2026-08-05",
"adults": 2,
"children": 1,
"status": "confirmed",
"channel": "booking_com",
"guest": {
"firstName": "Jana",
"lastName": "Marić",
"email": "jana@example.com",
"phone": "+38765123456"
},
"note": "Late arrival, about 23:00",
"locale": "de"
}Answer · 201
{
"booking": {
"id": "b3a91c08-6d24-4e57-a0b1-c2d3e4f5a6b7",
"confirmationNumber": "AP-7KQ2ZX",
"unitId": "6c1f2a9e-3b4d-4e5f-8a6b-7c8d9e0f1a2b",
"unitName": "Apartment 3",
"arrival": "2026-08-01",
"departure": "2026-08-05",
"nights": 4,
"status": "confirmed",
"guestName": "Jana Marić",
"guestEmail": "jana@example.com",
"guestPhone": "+38765123456",
"adults": 2,
"children": 1,
"total": "420.00",
"currency": "EUR",
"channel": "booking_com",
"createdAt": "2026-07-02T09:14:00Z",
"updatedAt": "2026-07-02T09:14:00Z"
}
}DELETE /api/v1/bookings/{id}
Key scope: write
Cancels the stay and frees its nights; nothing is deleted. A second call answers 200 with cancelled: false.
Answer · 200
{
"booking": {
"id": "b3a91c08-6d24-4e57-a0b1-c2d3e4f5a6b7",
"confirmationNumber": "AP-7KQ2ZX",
"unitId": "6c1f2a9e-3b4d-4e5f-8a6b-7c8d9e0f1a2b",
"unitName": "Apartment 3",
"arrival": "2026-08-01",
"departure": "2026-08-05",
"nights": 4,
"status": "cancelled",
"guestName": "Jana Marić",
"guestEmail": "jana@example.com",
"guestPhone": "+38765123456",
"adults": 2,
"children": 1,
"total": "420.00",
"currency": "EUR",
"channel": "booking_com",
"createdAt": "2026-07-02T09:14:00Z",
"updatedAt": "2026-07-02T09:14:00Z"
},
"cancelled": true
}GET /api/v1/availability
Key scope: read
Which nights are free, for one unit or all: from (default today) to (default 90 days later), at most 400 nights. booked covers the host's own stays and stays imported from other channels; blocked is a night the host closed.
Query parameters
unitid (UUID)
fromdate
todate
Answer · 200
{
"from": "2026-08-01",
"to": "2026-08-04",
"units": [
{
"unitId": "6c1f2a9e-3b4d-4e5f-8a6b-7c8d9e0f1a2b",
"unitName": "Apartment 3",
"nights": [
{
"date": "2026-08-01",
"available": false,
"reason": "booked"
},
{
"date": "2026-08-02",
"available": false,
"reason": "blocked"
},
{
"date": "2026-08-03",
"available": true,
"reason": null
}
]
}
]
}GET /api/v1/rates
Key scope: read
What each night costs, with the host's pricing rules applied, for one unit or all; at most 400 nights, with the same defaults as availability.
Query parameters
unitid (UUID)
fromdate
todate
Answer · 200
{
"from": "2026-08-01",
"to": "2026-08-03",
"units": [
{
"unitId": "6c1f2a9e-3b4d-4e5f-8a6b-7c8d9e0f1a2b",
"unitName": "Apartment 3",
"minNights": 2,
"currency": "EUR",
"rates": [
{
"unitId": "6c1f2a9e-3b4d-4e5f-8a6b-7c8d9e0f1a2b",
"date": "2026-08-01",
"price": "120.00",
"blocked": false
},
{
"unitId": "6c1f2a9e-3b4d-4e5f-8a6b-7c8d9e0f1a2b",
"date": "2026-08-02",
"price": "80.00",
"blocked": true
}
]
}
]
}PUT /api/v1/rates
Key scope: write
Sets one unit's prices and closed nights, at most 400 nights a request. Each row replaces the night: a row without price clears that night's price, and a row without blocked opens it.
Body
unitIdid (UUID)
required
rateslist of: object
required
rates[].datedate
required
rates[].pricedecimal number
may be empty
Left out, the night costs the unit's price again.
rates[].blockedtrue/false
Left out, the night is open.
Request
{
"unitId": "6c1f2a9e-3b4d-4e5f-8a6b-7c8d9e0f1a2b",
"rates": [
{
"date": "2026-08-01",
"price": "140.00"
},
{
"date": "2026-08-02",
"price": "140.00",
"blocked": false
},
{
"date": "2026-08-03",
"blocked": true
}
]
}Answer · 200
{
"unitId": "6c1f2a9e-3b4d-4e5f-8a6b-7c8d9e0f1a2b",
"written": 3
}Webhooks
Add an endpoint in Settings → API and webhooks, choose its events and copy the signing secret, which is shown once. A database trigger records each event when the change is saved, whichever screen, import or API call made it: every change to a booking, and every change to a night's own price or to whether it is closed. Other price changes send no event; see rates.updated below.
Events
reservation.created— New bookingsreservation.updated— Changed bookingsreservation.cancelled— Cancelled bookingsrates.updated— Prices and closed nightsping— Sent only by the Test button.
Every delivery is a POST with the body below: data is the booking exactly as GET /api/v1/bookings/{id} returns it, or, for rates.updated, one rate.
{
"event": "reservation.created",
"data": {
"id": "b3a91c08-6d24-4e57-a0b1-c2d3e4f5a6b7",
"confirmationNumber": "AP-7KQ2ZX",
"unitId": "6c1f2a9e-3b4d-4e5f-8a6b-7c8d9e0f1a2b",
"unitName": "Apartment 3",
"arrival": "2026-08-01",
"departure": "2026-08-05",
"nights": 4,
"status": "confirmed",
"guestName": "Jana Marić",
"guestEmail": "jana@example.com",
"guestPhone": "+38765123456",
"adults": 2,
"children": 1,
"total": "420.00",
"currency": "EUR",
"channel": "booking_com",
"createdAt": "2026-07-02T09:14:00Z",
"updatedAt": "2026-07-02T09:14:00Z"
}
}rates.updated is sent when a night's own entry on the calendar changes: a price is set or cleared for it, or it is closed or opened. Its price is that night's own price, which is final, or else the unit's price before the pricing rules: no season or weekend rule is in it, while GET /api/v1/rates applies them. A change to a pricing rule or to a unit's price sends no rates.updated, so software that passes prices on should take them from GET /api/v1/rates and read them again regularly.
Headers
X-Staywick-EventThe event's name.X-Staywick-TimestampWhen it was sent, in Unix seconds.X-Staywick-SignatureHMAC-SHA256 of the timestamp and the body, with the signing secret:sha256=<hmac-sha256(secret, "<timestamp>.<body>")>X-Staywick-DeliveryThe delivery's id, the same on every retry.
Events are sent moments after the change, and a scheduled run every few minutes sends anything still waiting. Answer with any 2xx within 10 seconds. Anything else is tried again, after these intervals: 1 minute, 5 minutes, 30 minutes, 2 hours, and 12 hours. Then it is given up, and Settings shows the endpoint's failures.
Every retry carries the same X-Staywick-Delivery, so handle each delivery once.
To check a delivery, compute the signature over the timestamp, a dot and the body exactly as received, and refuse old timestamps. In Node:
import crypto from "node:crypto";
export function verify(req, rawBody, secret) {
const ts = req.headers["x-staywick-timestamp"];
const sent = req.headers["x-staywick-signature"] ?? "";
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
const mine = `sha256=${crypto
.createHmac("sha256", secret)
.update(`${ts}.${rawBody}`, "utf8")
.digest("hex")}`;
const a = Buffer.from(mine);
const b = Buffer.from(String(sent));
return a.length === b.length && crypto.timingSafeEqual(a, b);
}