Developers

Partner Booking API

The Partner Booking API lets marketplaces, calendars, and integration platforms read a tenant’s services and availability and create bookings on their behalf. Signed webhooks report booking creation and cancellation events produced by the integration.

v1JSONHMAC-SHA256Beta

Authentication

Every request must include a Bearer token. Tenants generate and revoke keys in Settings → Integrations in Avena Flow. Each key belongs to one tenant and has specific permissions.

Authorization: Bearer afp_live_8k3...

Key format: afp_live_ prefix plus 32 random bytes in URL-safe base64.

List services

GET/api/v1/public/services

Returns active, bookable services for the authenticated tenant.

curl https://avenaflow.com/api/v1/public/services \
  -H "Authorization: Bearer afp_live_..."

Response

Get availability

GET/api/v1/public/availability

Returns open slots over a date range, honoring staff hours, blocks, and configured lead time.

ParamTypeNotes
service_idstringrequired — UUID returned by /services
fromYYYY-MM-DDoptional — defaults to today
toYYYY-MM-DDoptional — defaults to start date + 14 days (max 60)
staff_idstringoptional — filter to one staff member
curl "https://avenaflow.com/api/v1/public/availability?service_id=a7b1&from=2026-06-10&to=2026-06-17" \
  -H "Authorization: Bearer afp_live_..."

Create a booking

POST/api/v1/public/bookings

Creates a confirmed appointment in the tenant’s calendar. A contact is created when the email or phone does not match an existing client. Returns 409 if the slot becomes unavailable before confirmation.

Idempotency: send partner_reference_id. Repeating the request with the same value returns the original booking without creating a duplicate.

curl -X POST https://avenaflow.com/api/v1/public/bookings \
+  -H "Authorization: Bearer afp_live_..." \
+  -H "Content-Type: application/json" \
+  -d '{"service_id":"a7b1...","start_time":"2026-06-10T14:00:00Z","customer":{"first_name":"Jane","last_name":"Doe","email":"jane@example.com","phone":"+14015551234"},"partner_reference_id":"partner_res_42"}'

Response (201)

Cancel a booking

DELETE/api/v1/public/bookings/{id}

Soft-cancels a booking and reopens the slot. A key can only cancel bookings created by the same partner.

curl -X DELETE "https://avenaflow.com/api/v1/public/bookings/ap_9f2?reason=customer_request" \
  -H "Authorization: Bearer afp_live_..."

Webhooks and signatures

Bookings created or cancelled through this API produce signed events for the tenant’s active endpoints. Other change events are not yet part of the public contract.

Implemented events

  • booking.created
  • booking.cancelled

Request headers

POST /your/webhook HTTP/1.1
Content-Type: application/json
X-Avena-Signature: t=1717084800,v1=4f7b2...
X-Avena-Event: booking.cancelled
User-Agent: AvenaFlow-Webhooks/1.0

Verify the signature

Concatenate {timestamp}.{raw_body}, create an HMAC-SHA256 with the signing secret, and compare it with v1 in constant time. Reject old timestamps to prevent replay.

import crypto from 'crypto'

function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')))
  const ts = Number(parts.t)
  const expected = crypto.createHmac('sha256', secret).update(`${ts}.${rawBody}`).digest('hex')
  return crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected))
}

Retry policy

Delivery is attempted immediately. Failures remain queued for the retry worker; do not depend on an exact retry interval during beta.

iCal feed

GET/api/v1/public/calendar/{slug}.ics

Read-only iCal feed identified by the tenant’s public booking slug. Because the link does not require authentication, share it only when that calendar exposure is appropriate.

Errors

All errors return JSON with an error key and, when helpful, message.

StatusErrorMeaning
400missing_required_fieldsRequired body fields are missing
401missing_bearer_tokenAuthorization header is missing
401invalid_api_keyKey was not found or is invalid
401api_key_revokedKey was revoked by the tenant
403insufficient_scopeKey lacks the required permission
404service_not_foundService does not exist or is inactive
409slot_unavailableSlot became unavailable before confirmation