Skip to content

Partner API v1

A small, scoped booking API.

All responses are no-store. The key-derived application decides the tenant, enabled scopes, allowed locations and optional origin/IP restrictions.

Endpoints

GET/api/partner/v1/catalog

Published services and allowed locations. Use bounded limit/cursor paging.

catalog.read
GET/api/partner/v1/catalog/specialists

Published specialists narrowed by supported service/location filters.

catalog.read
GET/api/partner/v1/availability

Bounded free slots after current lead, schedule and capacity rules.

availability.read
POST/api/partner/v1/bookings

Guest booking with contact consent, external_reference and Idempotency-Key.

booking.create
GET/api/partner/v1/bookings/{pbr_reference}

Application-owned booking projection and current management version.

booking.manage
POST/api/partner/v1/bookings/{pbr_reference}/actions/{cancel|reschedule}

Versioned idempotent lifecycle change under current booking rules.

booking.manage

Authorization, envelopes and request tracing

http
GET /api/partner/v1/catalog?locale=en&limit=2 HTTP/1.1
Authorization: Bearer fnx_test_example_key_not_a_real_credential
Accept-Language: en
Origin: https://partner.example

HTTP/1.1 200 OK
Cache-Control: private, no-store
Referrer-Policy: no-referrer
X-Request-Id: <request_id>
X-RateLimit-Limit: <limit>
X-RateLimit-Remaining: <remaining>
X-RateLimit-Reset: <unix_seconds>

{
  "data": { "services": [], "next_cursor": null },
  "meta": { "request_id": "<request_id>", "version": "v1" }
}

Scope and credential policy

ScopeRoutesBoundary
catalog.readCatalog and specialistsOnly current published data allowed by the credential location policy.
availability.readAvailabilityOnly bounded available slots under current booking, capacity and lead-time rules.
booking.createCreate bookingExplicit customer consent, external_reference and Idempotency-Key are required.
booking.manageBooking read and actionsOnly an application-owned pbr_ reference; actions also require expected_version.
webhooks.manageOwner Control CenterWebhook configuration is managed in the protected owner workspace, not by a public API route.

Create booking

http
POST /api/partner/v1/bookings HTTP/1.1
Authorization: Bearer fnx_test_example_key_not_a_real_credential
Idempotency-Key: 7b1d9ed1-7f34-4ddf-9e01-example
Content-Type: application/json

{
  "service_id": "<published_service_id>",
  "location_id": "<optional_allowed_location_id>",
  "date": "2026-09-21",
  "start_time": "10:00",
  "external_reference": "partner-order-1042",
  "customer": {
    "name": "Test customer",
    "phone": "+15550001111",
    "consent_to_contact": true
  }
}

Current booking shape

  • Partner API v1 creates one service per booking. The documented service_id field is singular; sending an invented service_ids or composition_mode field is rejected.
  • Composite sequential or parallel service booking is available through the signed Feny widget and first-party booking flow, where the canonical booking engine validates combinations, staff capacity and current business rules.
  • Do not expose a Partner API credential in browser code. Use the public widget id and version for browser embeds, and keep Partner API calls on a trusted server.

Pagination and bounded reads

http
GET /api/partner/v1/catalog?locale=en&limit=25&cursor=<next_cursor> HTTP/1.1
Authorization: Bearer fnx_test_example_key_not_a_real_credential

{
  "data": {
    "services": ["..."],
    "next_cursor": "<opaque_cursor_or_null>"
  },
  "meta": { "request_id": "<request_id>", "version": "v1" }
}

Pagination rules

  • Catalog and specialist reads accept limit from 1 to 50 (default 25). Availability accepts limit from 1 to 96 (default 48).
  • Pass next_cursor exactly as returned. It is opaque and must not be decoded, constructed, shared across unrelated queries or used after changing filters.
  • Availability next_cursor represents the last returned slot start time for that exact availability query. A null next_cursor means there is no next page.
  • Availability is a current read, not a reservation. Re-read and let the create-booking request perform the final server-side capacity check.

Idempotent booking actions

http
POST /api/partner/v1/bookings/<pbr_reference>/actions/cancel HTTP/1.1
Authorization: Bearer fnx_test_example_key_not_a_real_credential
Idempotency-Key: 11111111-2222-4333-8444-example
Content-Type: application/json

{ "expected_version": 3 }

Idempotency and version policy

  • Use one 16-128 character Idempotency-Key for one logical write. Repeat the exact request after an uncertain result to obtain the safe replay; use a new key for a new operation.
  • Never reuse an idempotency key with changed input. The API returns 409 idempotency_key_reused rather than guessing which request is authoritative.
  • Retrieve a managed booking before cancel or reschedule, then send its latest management version as expected_version. A stale version can return a 409 booking_version_conflict.
  • Do not encode customer data, credentials or other sensitive values in Idempotency-Key or external_reference.

Errors and retries

ConditionResponsePartner action
Invalid or expired key401 invalid_api_keyRotate or select the correct environment; do not retry with another tenant selector.
Missing scope or credential restriction403 insufficient_scope / credential_restrictedChange the application policy in the owner Control Center.
Invalid request or unavailable booking400 invalid_request / 409 booking_unavailableCorrect the input or retrieve current availability; keep the original idempotency key only for the same logical write.
Missing record404 not_foundDo not infer tenant state or retry with a different tenant selector.
Quota response429 rate_limitedRespect Retry-After and rate-limit headers. Retry only after the stated window with bounded backoff.
Temporary service response503 service_unavailableUse bounded exponential backoff with jitter; preserve the same idempotency key only for the same write.
Reused idempotency key with changed input409 idempotency_key_reusedCreate a new logical operation and key; never mutate a replay request.
API reference | Feny Developers