Keegix Your dashboard

API for property managers

Last updated November 2026

In short

Properties and guest pages

Every property in Keegix has exactly one guest page (the link on your QR sign, keegix.com/p/…). The API gives you two views of the same thing:

You can create a property from either side. Everything follows the same rules as the editor: your plan's property count, guest passwords stored scrambled (never readable again), and when you change a section, its translation (if you have one) is removed so guests never see old instructions.

API keys

On your dashboard, under Manage many properties at once, type a name and tap Create key. The key starts with kgx_ and is shown only once: Keegix keeps a one-way scrambled copy, so nobody (including us) can read it back. If you lose it, revoke it and make another. You can have up to 10.

A key can read and change every one of your properties, so treat it like a password: keep it on your server, never in a web page or an app people download. Revoking a key stops it straight away.

Send the key with every request:

Authorization: Bearer kgx_your_key_here

(X-Api-Key: kgx_… works too.) All addresses start with https://keegix.com/api/. If your plan goes back to free, your keys pause and answer 402 until you're on Pro again.

How a row finds its property

Each item (or spreadsheet row) is matched against your properties only, in this order:

To give an existing property a reference, match it by id or slug and send external_id with it. Each reference can be used by one of your properties at a time. Send "external_id": null (JSON only) with an id to clear it.

Spreadsheet (CSV) upload

The easiest way: start from the template, save as CSV from Excel, Numbers or Google Sheets, and upload on your dashboard. Tap Check the file to see every change, then Save.

ColumnWhat it sets
external_id, id, slugWhich property (see matching)
nameProperty name shown at the top of the guest page
checkin, parking, rules, appliances, trash, local, emergency, checkoutThe text of that section of the guest page (up to 6,000 characters each)
wifi_name, wifi_password, wifiNetwork name, password, and any wifi notes
password / remove_passwordSet a guest password (4–100 characters), or yes to remove it
accent_color, bg_colorColours, like #1f4d3a
qr_style, qr_brandSign style (see styles) and yes/no for your brand colour on the sign
helper_offyes switches off the guest question helper on that page

From a script, send the file itself:

# Check first (saves nothing)
curl -X POST "https://keegix.com/api/bulk-import?dry_run=1" \
  -H "Authorization: Bearer $KEEGIX_KEY" \
  -H "Content-Type: text/csv" \
  --data-binary @properties.csv

# Then save
curl -X POST "https://keegix.com/api/bulk-import" \
  -H "Authorization: Bearer $KEEGIX_KEY" \
  -H "Content-Type: text/csv" \
  --data-binary @properties.csv

A form upload with the file in a field called file works too. Each result has a row (the spreadsheet line, header = 1) and a label (the row's external_id or name).

Properties: list, create and update

List: GET /api/bulk-properties

Your properties, oldest first. Optional: ?page=1&per_page=200 (200 at most) and ?external_id=UNIT-12 to find one.

curl "https://keegix.com/api/bulk-properties?per_page=50" \
  -H "Authorization: Bearer $KEEGIX_KEY"
{
  "page": 1, "per_page": 50, "total": 2, "total_pages": 1, "plan_limit": 5,
  "properties": [
    {
      "id": "k3j9x2m1q8w7e4r",
      "external_id": "UNIT-12",
      "name": "Harbour View Loft",
      "slug": "h7kq2m9wxp",
      "guest_url": "https://keegix.com/p/h7kq2m9wxp",
      "status": "live",
      "has_password": false,
      "accent_color": "#1f4d3a",
      "bg_color": "#f3f5f2",
      "helper_off": false,
      "qr_style": "tag-navy",
      "qr_brand": false,
      "created": "2026-11-04 15:02:11.120Z",
      "updated": "2026-11-04 15:02:11.120Z"
    }
  ]
}

status is live, paused (more properties than your plan covers: only the oldest ones stay live) or pending (made from a binder upload, waiting for the owner's first sign-in).

Create or update: POST /api/bulk-properties

Send up to 100 items. Only the fields you send change.

curl -X POST "https://keegix.com/api/bulk-properties" \
  -H "Authorization: Bearer $KEEGIX_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "properties": [
      { "external_id": "UNIT-12", "name": "Harbour View Loft", "qr_style": "tag-navy" },
      { "external_id": "UNIT-14", "name": "Garden Suite", "password": "garden2026" },
      { "slug": "h7kq2m9wxp", "external_id": "UNIT-9" }
    ]
  }'
FieldType and rules
id, slug, external_idText. Which property (see matching)
nameText, up to 100 characters
accent_color, bg_colorText like #1f4d3a
passwordText, 4–100 characters. Stored scrambled; never returned
remove_passwordtrue removes the guest password
helper_offtrue or false: the guest question helper
qr_styletag-yellow, tag-navy, tag-dots, house, door, bubble, circle or square
qr_brandtrue or false: your accent colour on the sign

Any other field is refused (so a typo doesn't go unnoticed). Photos and logos are added in the editor.

Guest pages: list, create and update

List: GET /api/bulk-pages

Same as the property list, with each page's content. per_page is 50 at most.

{
  "page": 1, "per_page": 50, "total": 1, "total_pages": 1, "plan_limit": 5,
  "pages": [
    {
      "id": "k3j9x2m1q8w7e4r", "external_id": "UNIT-12", "name": "Harbour View Loft",
      "slug": "h7kq2m9wxp", "guest_url": "https://keegix.com/p/h7kq2m9wxp",
      "status": "live", "has_password": false,
      "content": { "checkin": "Check-in is from 4 pm…", "wifi": "", "wifi_name": "HarbourGuest", "wifi_password": "…", "parking": "…" },
      "sections": [
        { "id": "a1b2c3d4e5f6", "type": "checkin", "title": "Check-in", "body": "Check-in is from 4 pm…", "enabled": true },
        { "id": "0f9e8d7c6b5a", "type": "wifi", "title": "Wifi", "body": "", "enabled": true, "wifi_name": "HarbourGuest", "wifi_password": "…" }
      ],
      "updated": "2026-11-04 15:02:11.120Z"
    }
  ]
}

Create or update: POST /api/bulk-pages

Match each page like a property (id, slug or external_id; name works here too), then send the content one of two ways:

curl -X POST "https://keegix.com/api/bulk-pages" \
  -H "Authorization: Bearer $KEEGIX_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "pages": [
      {
        "external_id": "UNIT-12",
        "content": {
          "checkin": "Check-in is from 4 pm. We text you the lockbox code on arrival day.",
          "wifi_name": "HarbourGuest",
          "wifi_password": "new-password-for-november"
        }
      }
    ]
  }'

Sending "" for a content field empties it (an empty section isn't shown to guests).

What comes back

Create and update calls answer 200 with one result per item, in the order you sent them. One bad item never stops the others.

{
  "dry_run": false,
  "summary": { "created": 1, "updated": 1, "unchanged": 0, "failed": 1 },
  "results": [
    { "index": 0, "ok": true, "action": "created", "changes": ["name", "qr_style", "external_id"], "property": { … } },
    { "index": 1, "ok": true, "action": "updated", "changes": ["password"], "property": { … } },
    { "index": 2, "ok": false, "error": "not_found", "message": "No property of yours has that slug." }
  ]
}

Errors

Every error has a short error code and a plain-English message you can show to a person.

Whole requestMeaning
401 authNo key, a mistyped key, or a revoked key
402 pro_requiredThe account isn't on Pro (keys pause until it is)
400 bad_request, bad_csv, unknown_columnThe body or file couldn't be read; the message says what to fix
413 too_many, too_bigOver 100 items or 1 MB: split it
500 serverOur side. Send the same request again; anything already saved comes back unchanged
One itemMeaning
not_foundNo property of yours has that id or slug
limitYour plan's properties are all used. Add more from Manage billing
duplicateThe same property appears twice in one request; only the first is used
external_id_takenAnother of your properties already has that reference
unknown_fieldA field this endpoint doesn't take (often a typo)
invalid, bad_colour, bad_password, bad_styleA value isn't allowed; the message says which and why

Limits and good habits

Questions or something missing? Email contact@keegix.com.