Keyguides Association Integration API (1.6.2)

Download OpenAPI specification:

Read-only API for associations to display member guides and tours on an external website. Bookings complete on the Keyguides Connect portal (not via this API).

Integration model

Server-to-server proxy only. The association operates a backend (BFF) that calls this API with an API key; its public website calls that backend, never Keyguides directly. No local catalog persistence — proxy each request, with optional ephemeral in-memory cache (≤60s catalog, ≤300s reference data, ≤30s availability). Webhooks are the cache invalidation channel.

Booking

Use links.book.url in the browser to redirect to keyguidesconnect.com. Build deep links from links.book.hrefTemplate with the user's selection (date, time, groupSize, offeringId, guideId). Integrator alias paxgroupSize. Time format: HH:mm (24h) in the guide's IANA timezone. URL-encode all values.

Attribution

Every portal URL carries kg_assoc, utm_source, utm_medium (and optional utm_campaign). Integrators must not strip these params. Do not use ref (reserved for Tolt partner referrals).

Rate limits

Every response includes X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. On 429, also Retry-After. Back off proactively when Remaining is low — do not wait for 429.

Availability

Date range capped at 90 days (400 range_too_large otherwise). Slot times are RFC 3339 with numeric offset in the guide's IANA timeZone. 200 with empty availability means bookable but no slots in window; 409 guide_not_bookable means the guide cannot be booked at all.

Money

All price fields are integers in minor currency units (e.g. EUR/USD cents; zero-decimal currencies like JPY use the major unit). Format with the resource currency field.

Production URLs

  • Portal: https://keyguidesconnect.com
  • API: https://api.keyguidesconnect.com/v1

Association

Get authenticated association profile and attribution defaults

Authorizations:
ApiKeyAuth

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "slug": "string",
  • "status": "INACTIVE",
  • "type": "ASSOCIATION",
  • "website": "http://example.com",
  • "featureImageUrl": "http://example.com",
  • "countryCode": "string",
  • "currency": "EUR",
  • "portalBaseUrl": "https://keyguidesconnect.com",
  • "attribution": {
    },
  • "links": {
    }
}

Guides

List published guides in this association

Authorizations:
ApiKeyAuth
query Parameters
page
integer >= 1
Default: 1
limit
integer [ 1 .. 100 ]
Default: 20
city
string

City ID or slug (comma-separated)

country
string

Country code (comma-separated)

language
string

Language code (comma-separated)

interest
string

Interest ID or slug (comma-separated)

bookableOnly
boolean
Default: false

If true, only guides meeting Keyguides bookability requirements

orderBy
string
Default: "publishedAt"
Enum: "createdAt" "publishedAt" "name"
sortOrder
string
Default: "desc"
Enum: "asc" "desc"
header Parameters
If-None-Match
string

Return 304 Not Modified when unchanged

Accept-Language
string
Example: en

Locale for translated tour/guide fields

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "pagination": {
    },
  • "attribution": {
    }
}

Get guide profile (UUID or username)

Authorizations:
ApiKeyAuth
path Parameters
guideId
required
string

Guide UUID or username

header Parameters
If-None-Match
string

Return 304 Not Modified when unchanged

Accept-Language
string
Example: en

Locale for translated tour/guide fields

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "username": "string",
  • "headline": "string",
  • "introduction": "string",
  • "profilePictureUrl": "http://example.com",
  • "published": true,
  • "isBookable": true,
  • "paymentsEnabled": true,
  • "currency": "EUR",
  • "pricePerHourMinorUnits": 0,
  • "displayName": "string",
  • "languages": [
    ],
  • "cities": [
    ],
  • "interests": [
    ],
  • "memberType": {
    },
  • "links": {
    },
  • "images": [],
  • "cancellationPolicy": "string",
  • "availablePerHour": true
}

List tours for one guide (paginated). For association-wide browse use `/tours`.

Authorizations:
ApiKeyAuth
path Parameters
guideId
required
string

Guide UUID or username

query Parameters
page
integer >= 1
Default: 1
limit
integer [ 1 .. 100 ]
Default: 20
header Parameters
If-None-Match
string

Return 304 Not Modified when unchanged

Accept-Language
string
Example: en

Locale for translated tour/guide fields

Responses

Response samples

Content type
application/json
{
  • "guideId": "57a2c85a-fbd7-4e1d-a11d-cd419b69c36a",
  • "username": "string",
  • "data": [
    ],
  • "pagination": {
    },
  • "attribution": {
    }
}

Tours

List published tours bookable through this association's guides

Authorizations:
ApiKeyAuth
query Parameters
page
integer >= 1
Default: 1
limit
integer [ 1 .. 100 ]
Default: 20
city
string

City ID or slug (comma-separated)

country
string

Country code (comma-separated)

language
string

Language code (comma-separated)

interest
string

Interest ID or slug (comma-separated)

guideId
string

Filter to tours linked to this guide (UUID or username)

guests
integer >= 1

Affects displayed price (integrator alias pax)

dateFrom
string <date>
dateTo
string <date>
header Parameters
Accept-Language
string
Example: en

Locale for translated tour/guide fields

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "pagination": {
    },
  • "attribution": {
    }
}

Get tour detail (UUID or slug)

Authorizations:
ApiKeyAuth
path Parameters
tourId
required
string

Tour UUID or slug

header Parameters
Accept-Language
string
Example: en

Locale for translated tour/guide fields

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "slug": "string",
  • "introduction": "string",
  • "description": "string",
  • "featureImageUrl": "http://example.com",
  • "imageUrls": [],
  • "cityId": "c903c051-7337-48de-bbe0-bca96fcde3f4",
  • "city": {
    },
  • "isBookable": true,
  • "currency": "EUR",
  • "links": {
    },
  • "offerings": [
    ],
  • "guides": [
    ]
}

Reference data

Cities (association-scoped) for filter UIs

Authorizations:
ApiKeyAuth
query Parameters
scope
string
Default: "all"
Enum: "all" "guides" "tours"

Which catalog to derive facets from

header Parameters
Accept-Language
string
Example: en

Locale for translated tour/guide fields

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "meta": {
    }
}

Countries (association-scoped) for filter UIs

Authorizations:
ApiKeyAuth
query Parameters
scope
string
Default: "all"
Enum: "all" "guides" "tours"

Which catalog to derive facets from

header Parameters
Accept-Language
string
Example: en

Locale for translated tour/guide fields

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "meta": {
    }
}

Languages (association-scoped) for filter UIs

Authorizations:
ApiKeyAuth
query Parameters
scope
string
Default: "all"
Enum: "all" "guides" "tours"

Which catalog to derive facets from

header Parameters
Accept-Language
string
Example: en

Locale for translated tour/guide fields

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "meta": {
    }
}

Interests/categories (association-scoped) for filter UIs

Authorizations:
ApiKeyAuth
query Parameters
scope
string
Default: "all"
Enum: "all" "guides" "tours"

Which catalog to derive facets from

header Parameters
Accept-Language
string
Example: en

Locale for translated tour/guide fields

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "meta": {
    }
}

Availability

Get bookable time slots for a guide

200 with empty availability = bookable but no slots in window. 409 guide_not_bookable = guide cannot be booked at all. 400 range_too_large when span > 90 days.

Authorizations:
ApiKeyAuth
path Parameters
guideId
required
string

Guide UUID or username

query Parameters
fromDate
required
string <date>
Example: fromDate=2026-06-01

Inclusive start (calendar date in guide timeZone). Max span 90 days.

toDate
required
string <date>
Example: toDate=2026-06-30

Inclusive end. >= fromDate, max 90 days span.

durationMinutes
integer >= 15
Example: durationMinutes=120

Slot length in minutes. Required unless offeringId is provided.

offeringId
string <uuid>

Optional; when set, durationMinutes may be derived from the offering

Responses

Response samples

Content type
application/json
{
  • "guideId": "57a2c85a-fbd7-4e1d-a11d-cd419b69c36a",
  • "username": "string",
  • "durationMinutes": 0,
  • "fromDate": "2019-08-24",
  • "toDate": "2019-08-24",
  • "timeZone": "Europe/Paris",
  • "offeringId": "539ace7f-4593-4a19-ba60-d31118c061f5",
  • "availability": [
    ],
  • "links": {
    }
}

Get bookable time slots for a tour (requires `guideId`)

Authorizations:
ApiKeyAuth
path Parameters
tourId
required
string

Tour UUID or slug

query Parameters
guideId
required
string
Example: guideId=jane-doe

Guide whose calendar to read (must be linked to the tour and ACTIVE)

fromDate
required
string <date>
Example: fromDate=2026-06-01

Inclusive start (calendar date in guide timeZone). Max span 90 days.

toDate
required
string <date>
Example: toDate=2026-06-30

Inclusive end. >= fromDate, max 90 days span.

durationMinutes
integer >= 15
Example: durationMinutes=120

Slot length in minutes. Required unless offeringId is provided.

offeringId
string <uuid>

Recommended; duration is taken from the offering

Responses

Response samples

Content type
application/json
{
  • "tourId": "eb2f92e7-0760-4174-a0f6-c120b0ef2ec8",
  • "tourSlug": "string",
  • "guideId": "57a2c85a-fbd7-4e1d-a11d-cd419b69c36a",
  • "offeringId": "539ace7f-4593-4a19-ba60-d31118c061f5",
  • "durationMinutes": 0,
  • "fromDate": "2019-08-24",
  • "toDate": "2019-08-24",
  • "timeZone": "Europe/Paris",
  • "availability": [
    ],
  • "links": {
    }
}

Webhooks

Guide approved as ACTIVE member Webhook

Authorizations:
ApiKeyAuth
header Parameters
X-Keyguides-Event-Id
required
string

Unique delivery id (same as WebhookEnvelope.id); use for idempotency

X-Keyguides-Signature
required
string
Example: t=1716300000,v1=abc123def456...

t={unix_seconds},v1={hex_hmac}. Signed payload: {t}.{raw_body_bytes}. HMAC-SHA256 over signing_secret. Reject if abs(now - t) > 300s.

X-Keyguides-Timestamp
string

Duplicate of t in signature header (convenience)

Request Body schema: application/json
required
id
required
string

Event id for deduplication

type
required
string
Enum: "guide.member.activated" "guide.member.deactivated" "guide.updated" "tour.published" "tour.unpublished" "tour.updated" "guide.calendar.disconnected" "guide.calendar.reconnected"
createdAt
required
string <date-time>
required
MemberWebhookData (object) or GuideUpdatedWebhookData (object) or TourWebhookData (object) or GuideCalendarWebhookData (object)

Payload shape depends on type

Responses

Request samples

Content type
application/json
{
  • "id": "string",
  • "type": "guide.member.activated",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": {
    }
}

Guide membership ended or deactivated Webhook

Authorizations:
ApiKeyAuth
header Parameters
X-Keyguides-Event-Id
required
string

Unique delivery id (same as WebhookEnvelope.id); use for idempotency

X-Keyguides-Signature
required
string
Example: t=1716300000,v1=abc123def456...

t={unix_seconds},v1={hex_hmac}. Signed payload: {t}.{raw_body_bytes}. HMAC-SHA256 over signing_secret. Reject if abs(now - t) > 300s.

X-Keyguides-Timestamp
string

Duplicate of t in signature header (convenience)

Request Body schema: application/json
required
id
required
string

Event id for deduplication

type
required
string
Enum: "guide.member.activated" "guide.member.deactivated" "guide.updated" "tour.published" "tour.unpublished" "tour.updated" "guide.calendar.disconnected" "guide.calendar.reconnected"
createdAt
required
string <date-time>
required
MemberWebhookData (object) or GuideUpdatedWebhookData (object) or TourWebhookData (object) or GuideCalendarWebhookData (object)

Payload shape depends on type

Responses

Request samples

Content type
application/json
{
  • "id": "string",
  • "type": "guide.member.activated",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": {
    }
}

Guide profile or bookability changed Webhook

Authorizations:
ApiKeyAuth
header Parameters
X-Keyguides-Event-Id
required
string

Unique delivery id (same as WebhookEnvelope.id); use for idempotency

X-Keyguides-Signature
required
string
Example: t=1716300000,v1=abc123def456...

t={unix_seconds},v1={hex_hmac}. Signed payload: {t}.{raw_body_bytes}. HMAC-SHA256 over signing_secret. Reject if abs(now - t) > 300s.

X-Keyguides-Timestamp
string

Duplicate of t in signature header (convenience)

Request Body schema: application/json
required
id
required
string

Event id for deduplication

type
required
string
Enum: "guide.member.activated" "guide.member.deactivated" "guide.updated" "tour.published" "tour.unpublished" "tour.updated" "guide.calendar.disconnected" "guide.calendar.reconnected"
createdAt
required
string <date-time>
required
MemberWebhookData (object) or GuideUpdatedWebhookData (object) or TourWebhookData (object) or GuideCalendarWebhookData (object)

Payload shape depends on type

Responses

Request samples

Content type
application/json
{
  • "id": "string",
  • "type": "guide.member.activated",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": {
    }
}

Tour published in association scope Webhook

Authorizations:
ApiKeyAuth
header Parameters
X-Keyguides-Event-Id
required
string

Unique delivery id (same as WebhookEnvelope.id); use for idempotency

X-Keyguides-Signature
required
string
Example: t=1716300000,v1=abc123def456...

t={unix_seconds},v1={hex_hmac}. Signed payload: {t}.{raw_body_bytes}. HMAC-SHA256 over signing_secret. Reject if abs(now - t) > 300s.

X-Keyguides-Timestamp
string

Duplicate of t in signature header (convenience)

Request Body schema: application/json
required
id
required
string

Event id for deduplication

type
required
string
Enum: "guide.member.activated" "guide.member.deactivated" "guide.updated" "tour.published" "tour.unpublished" "tour.updated" "guide.calendar.disconnected" "guide.calendar.reconnected"
createdAt
required
string <date-time>
required
MemberWebhookData (object) or GuideUpdatedWebhookData (object) or TourWebhookData (object) or GuideCalendarWebhookData (object)

Payload shape depends on type

Responses

Request samples

Content type
application/json
{
  • "id": "string",
  • "type": "guide.member.activated",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": {
    }
}

Tour unpublished or removed from catalog Webhook

Authorizations:
ApiKeyAuth
header Parameters
X-Keyguides-Event-Id
required
string

Unique delivery id (same as WebhookEnvelope.id); use for idempotency

X-Keyguides-Signature
required
string
Example: t=1716300000,v1=abc123def456...

t={unix_seconds},v1={hex_hmac}. Signed payload: {t}.{raw_body_bytes}. HMAC-SHA256 over signing_secret. Reject if abs(now - t) > 300s.

X-Keyguides-Timestamp
string

Duplicate of t in signature header (convenience)

Request Body schema: application/json
required
id
required
string

Event id for deduplication

type
required
string
Enum: "guide.member.activated" "guide.member.deactivated" "guide.updated" "tour.published" "tour.unpublished" "tour.updated" "guide.calendar.disconnected" "guide.calendar.reconnected"
createdAt
required
string <date-time>
required
MemberWebhookData (object) or GuideUpdatedWebhookData (object) or TourWebhookData (object) or GuideCalendarWebhookData (object)

Payload shape depends on type

Responses

Request samples

Content type
application/json
{
  • "id": "string",
  • "type": "guide.member.activated",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": {
    }
}

Tour content or offerings changed Webhook

Authorizations:
ApiKeyAuth
header Parameters
X-Keyguides-Event-Id
required
string

Unique delivery id (same as WebhookEnvelope.id); use for idempotency

X-Keyguides-Signature
required
string
Example: t=1716300000,v1=abc123def456...

t={unix_seconds},v1={hex_hmac}. Signed payload: {t}.{raw_body_bytes}. HMAC-SHA256 over signing_secret. Reject if abs(now - t) > 300s.

X-Keyguides-Timestamp
string

Duplicate of t in signature header (convenience)

Request Body schema: application/json
required
id
required
string

Event id for deduplication

type
required
string
Enum: "guide.member.activated" "guide.member.deactivated" "guide.updated" "tour.published" "tour.unpublished" "tour.updated" "guide.calendar.disconnected" "guide.calendar.reconnected"
createdAt
required
string <date-time>
required
MemberWebhookData (object) or GuideUpdatedWebhookData (object) or TourWebhookData (object) or GuideCalendarWebhookData (object)

Payload shape depends on type

Responses

Request samples

Content type
application/json
{
  • "id": "string",
  • "type": "guide.member.activated",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": {
    }
}

Guide calendar disconnected (availability invalid immediately) Webhook

Authorizations:
ApiKeyAuth
header Parameters
X-Keyguides-Event-Id
required
string

Unique delivery id (same as WebhookEnvelope.id); use for idempotency

X-Keyguides-Signature
required
string
Example: t=1716300000,v1=abc123def456...

t={unix_seconds},v1={hex_hmac}. Signed payload: {t}.{raw_body_bytes}. HMAC-SHA256 over signing_secret. Reject if abs(now - t) > 300s.

X-Keyguides-Timestamp
string

Duplicate of t in signature header (convenience)

Request Body schema: application/json
required
id
required
string

Event id for deduplication

type
required
string
Enum: "guide.member.activated" "guide.member.deactivated" "guide.updated" "tour.published" "tour.unpublished" "tour.updated" "guide.calendar.disconnected" "guide.calendar.reconnected"
createdAt
required
string <date-time>
required
MemberWebhookData (object) or GuideUpdatedWebhookData (object) or TourWebhookData (object) or GuideCalendarWebhookData (object)

Payload shape depends on type

Responses

Request samples

Content type
application/json
{
  • "id": "string",
  • "type": "guide.member.activated",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": {
    }
}

Guide calendar reconnected Webhook

Authorizations:
ApiKeyAuth
header Parameters
X-Keyguides-Event-Id
required
string

Unique delivery id (same as WebhookEnvelope.id); use for idempotency

X-Keyguides-Signature
required
string
Example: t=1716300000,v1=abc123def456...

t={unix_seconds},v1={hex_hmac}. Signed payload: {t}.{raw_body_bytes}. HMAC-SHA256 over signing_secret. Reject if abs(now - t) > 300s.

X-Keyguides-Timestamp
string

Duplicate of t in signature header (convenience)

Request Body schema: application/json
required
id
required
string

Event id for deduplication

type
required
string
Enum: "guide.member.activated" "guide.member.deactivated" "guide.updated" "tour.published" "tour.unpublished" "tour.updated" "guide.calendar.disconnected" "guide.calendar.reconnected"
createdAt
required
string <date-time>
required
MemberWebhookData (object) or GuideUpdatedWebhookData (object) or TourWebhookData (object) or GuideCalendarWebhookData (object)

Payload shape depends on type

Responses

Request samples

Content type
application/json
{
  • "id": "string",
  • "type": "guide.member.activated",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": {
    }
}