sandbox:sandbox:ci:48600190
v2v3

The Avvail Guest Book API uses OAuth 2.0 with the Client Credentials flow to secure access. This approach is ideal for server-to-server communications, where your application requests an access token using a Client ID and Client Secret.

Overview

  1. Obtain Your Credentials — request a Client ID and Client Secret from our support team. Typically, you'll receive sandbox credentials first, then production credentials when you're ready.
  2. Request an Access Token — send a POST request to the relevant token URL.
  3. Use the Access Token — include the token in the Authorization header when calling the API.

Client Credentials

When integrating with the Guest Book API, you will be provided with:

  • Client ID: A unique identifier for your application. This value is public and is used to identify your application during the OAuth flow.
  • Client Secret: A confidential value that must be kept secure. This secret is used in conjunction with your Client ID when obtaining an access token.

Important: Always store your Client Secret in a secure, encrypted location, and never log it in plaintext.

Access Tokens

Requesting Tokens

Tokens are granted via the OAuth 2.0 Client Credentials flow. Send a POST request to the relevant token URL:

  • Sandbox: https://sandbox.auth.avvail.com/oauth/token
  • Production: https://auth.avvail.com/oauth/token

Request Example

curl -X POST https://auth.avvail.com/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET",
    "audience": "https://api.avvail.com/",
    "grant_type": "client_credentials"
  }'

Response Example

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "scope": "reservations:read",
  "expires_in": 86400,
  "token_type": "Bearer"
}

Verifying Tokens

Each access token is a JWT (JSON Web Token) containing standard OAuth 2.0 claims. A decoded token looks like:

{
  "iss": "https://auth.avvail.com/",
  "sub": "xRt7hZmGvA9KsL2Dy5EbXfJ8iNqW3uP6@clients",
  "aud": "https://api.avvail.com/",
  "iat": 1677721600,
  "exp": 1677807600,
  "scope": "reservations:read venues:read availability:read",
  "gty": "client-credentials",
  "azp": "xRt7hZmGvA9KsL2Dy5EbXfJ8iNqW3uP6",
  "org_id": "org_7f3c2b1a8e4d4f9c"
}

Verify the token's signature using the JSON Web Key Set (JWKS) at https://auth.avvail.com/.well-known/jwks.json. Use a standard JWT library to perform RS256 signature validation.

Token Claims

Claim Description
azp Authorized party — your Client ID. Identifies the API caller.
scope Space-delimited list of granted scopes. Authorizes which endpoints can be called.
org_id Organization id. When present, identifies the entity (brand or distribution channel) the token was issued for. The server uses this to resolve entity context automatically.
aud Audience. Must equal https://api.avvail.com/.
exp Expiration timestamp (seconds since epoch).

Using Tokens

Include the token in the Authorization header for every API request:

Authorization: Bearer <ACCESS_TOKEN>

Refreshing Tokens

Tokens are not refreshable via a refresh token. Request a new token using the same Client ID and Client Secret before the current token expires. If your application runs continuously, schedule a refresh before expiration to avoid interrupted service.

Token Expiration

By default, tokens expire 24 hours after issuance. If you need a shorter token duration, contact our support team to adjust the default settings.

Entity Context

Every v2 request is scoped to a single entity (brand or distribution channel). The server resolves the entity for each request automatically, in this order:

  1. JWT org_id claim (recommended) — when your access token is bound to an organization, the corresponding entity is used. Entity context is bound to the token and cannot be tampered with at the request layer. See Requesting an Organization-Bound Token below.
  2. X-Entity-Id request header (deprecated) — used when the token has no org_id claim. Pass the entity's UUID:

    X-Entity-Id: 7f3c2b1a-8e4d-4f9c-a6b2-3d5e1a7c9f2b
    

    When the token carries an org_id, the header is ignored; the token-bound entity always wins. The header is deprecated and will eventually be retired in favor of token-bound entity context via org_id. No sunset date has been set; existing integrations continue to work and will receive adequate notice before any removal. New integrations should use organization-bound tokens from the start.

  3. Default entity — if neither org_id nor X-Entity-Id is present, the entity configured as your credential's default is used.

Your credentials may be linked to one or more entities. Requests targeting an entity that is not assigned to your credentials are rejected with 403 Forbidden. If the resolved entity does not exist, the response is 404 Not Found.

Requesting an Organization-Bound Token

Your credentials are pre-configured to issue organization-bound tokens for each entity assigned to them — no setup is required on your side.

  1. Include the organization parameter when requesting a token. Pass the org_id of the entity you want to target:

    curl -X POST https://auth.avvail.com/oauth/token \
      -H "Content-Type: application/json" \
      -d '{
        "client_id": "YOUR_CLIENT_ID",
        "client_secret": "YOUR_CLIENT_SECRET",
        "audience": "https://api.avvail.com/",
        "grant_type": "client_credentials",
        "organization": "org_7f3c2b1a8e4d4f9c"
      }'
    

    The returned access token carries an org_id JWT claim matching the entity. To discover the org_id values for your entities, see Discovering org_id values below.

  2. Use the token. Include it in the Authorization header for every API request. The server resolves entity context from the token's org_id claim; any X-Entity-Id value in the request is silently ignored.

Existing integrations that authenticate without the organization parameter and pass X-Entity-Id continue to work unchanged. See the API v2 Migration Guide for the upgrade narrative.

Discovering org_id values

Each entity exposed via GET /v2/entities carries an org_id field — the organization identifier you pass as the organization parameter in token requests to target that entity. Call the endpoint with any valid token (the response is scoped to the entities your credentials are authorized for) and read the org_id from each entry:

curl https://api.avvail.com/v2/entities \
  -H "Authorization: Bearer <ACCESS_TOKEN>"
{
  "data": [
    {
      "id": "7f3c2b1a-8e4d-4f9c-a6b2-3d5e1a7c9f2b",
      "name": "Acme Hotels Production",
      "org_id": "org_7f3c2b1a8e4d4f9c",
      "...": "..."
    }
  ],
  "pagination": { "...": "..." }
}

For entities whose organization has not yet been provisioned, org_id is null. In that case, omit the organization parameter when requesting a token — the token will fall back to your identity's default entity for the request's context.

Identity Introspection

For self-introspection (your identity's effective status, default entity, associated entity IDs, and the IDs of any delegated identities you manage), call GET /v2/identities/me:

curl https://api.avvail.com/v2/identities/me \
  -H "Authorization: Bearer <ACCESS_TOKEN>"

The endpoint requires a valid access token but no specific OAuth scope — introspection is a baseline capability. The response is wrapped in the standard v2 {data: ...} envelope and is polymorphic by type:

{
  "data": {
    "id": "8d2e1c4b-9a7f-4e3d-b5c8-1f6a3d9c2e7b",
    "type": "partner",
    "name": "Acme Hotels Production",
    "client_id": "xRt7hZmGvA9KsL2Dy5EbXfJ8iNqW3uP6",
    "status": "active",
    "default_entity_id": "7f3c2b1a-8e4d-4f9c-a6b2-3d5e1a7c9f2b",
    "associated_entity_ids": ["7f3c2b1a-..."],
    "delegated_identity_ids": ["1e3d5c7b-..."],
    "created_at": "2025-08-12T14:23:01Z",
    "updated_at": "2026-04-30T09:11:45Z"
  }
}

A delegated identity sees parent_identity_id (the partner that owns it) instead of delegated_identity_ids. Suspended identities still receive a 200 OK with status: "suspended", plus suspension_source ("self" or "parent") and suspended_at populated — the endpoint is designed to help you diagnose your own state when other endpoints are returning 403 Forbidden for suspension reasons.

associated_entity_ids lists only currently active entities. Resolve each ID to a full record (including org_id) via GET /v2/entities.

The me path convention

Where :id would normally appear in an identity-scoped path (for example /v2/identities/:id/…), pass the literal string me to refer to the caller's own identity. The server resolves me to the identity carried by your JWT. This convention is reserved for identity-scoped paths in this API.

Delegate listing (GET /v2/identities/me/delegates)

If you are a partner identity, GET /v2/identities/me/delegates returns the full record for each delegate you manage, paginated using the standard ?page= / ?limit= query parameters. The response uses the v2 list envelope:

{
  "data": [
    {
      "id": "1e3d5c7b-...",
      "type": "delegate",
      "name": "Acme Boutique Boston",
      "parent_identity_id": "8d2e1c4b-...",
      "...": "..."
    }
  ],
  "pagination": { "current_page": 1, "total_pages": 1, "total_items": 1, "items_per_page": 20 }
}

Delegated identities calling GET /v2/identities/me/delegates receive {"data": [], "pagination": {...}} with HTTP 200 — delegates cannot themselves have delegates. This is intentional, not an error.

To fetch a single delegate by ID, call GET /v2/identities/me/delegates/:id. Reading a delegate that does not belong to the calling partner returns 404 Not Found rather than 403 Forbidden, so the endpoint cannot be used as an existence oracle for arbitrary delegate IDs.

Scopes

API credentials are issued with specific scopes that determine which endpoints are accessible. The v2 API supports the following scopes:

Scope Description
availability:read Query real-time availability options
commitments:read Read your commitments
commitments:update Update your commitments
entities:create Create entities
entities:read Read entity data
entities:update Update entities
entities:upload_logo Upload entity logos
holds:create Create temporary capacity holds
holds:delete Release capacity holds early
markets:read List geographic markets for multi-venue search
reservations:create Create reservations
reservations:read Read reservation data
reservations:update Modify existing reservations
reservations:cancel Cancel reservations
venues:read Read venue data

To adjust the scopes assigned to your credentials, email support@avvail.com.

Security Best Practices

  • Use Secure Storage: Store the Client Secret and access tokens in a secure, encrypted location (e.g., environment variables or a secrets manager). Do not commit them to source control or include them directly in application code.
  • Never Log Secrets or Tokens in Plaintext: Avoid printing the Client Secret or access tokens to logs. If logging is necessary for debugging, redact or mask the critical parts (e.g., only log the first 4 and last 4 characters).
  • Verify and Monitor: Verify all access tokens and monitor API usage to detect suspicious activity. If you suspect credentials have been leaked, rotate them immediately.