Skip to content

For Partners

You are a partner if you are a company or large customer integrating many Beyond users on a backend you control — white-label products, multi-tenant platforms, or server-to-server automation. Partners authenticate with OAuth2 client credentials on a confidential client, can narrow access to a single Beyond user or login with user_id / credential_id, and are typically protected by an IP allowlist.

This is the path for trusted backend services that can store a client secret securely. This page is the end-to-end path: how authentication and token scoping work, then the onboarding flow from creating a user to activating a listing.

If instead you are an individual Beyond user automating your own listings, see For Personal Users.

When To Use This Path

Choose this profile if your integration:

  • Runs on your servers, workers, or scheduled jobs.
  • Needs machine-to-machine access without an end-user browser step.
  • May optionally narrow access to one Beyond user at a time with user_id.
  • May optionally narrow a user-scoped token further with credential_id.
Setting Value
App mode partner
Client type confidential
Primary grant client_credentials
Access token lifetime 1 hour

For a comparison with personal automation flows and personal access tokens, read the Authentication overview first.

Get An Access Token

Confidential clients use the client credentials grant at /o/token/ and then send the access token on /api/v1/* requests.

sequenceDiagram
    participant Partner as PartnerBackend
    participant Token as OAuthTokenEndpoint
    participant API as PartnersAPI

    Partner->>Token: POST /o/token/ grant_type=client_credentials
    Note right of Partner: client_id, client_secret, scope optional user_id credential_id
    Token-->>Partner: access_token, expires_in, token_type Bearer
    Partner->>API: GET /api/v1/... Authorization Bearer access_token
    API-->>Partner: JSON API response
curl -X POST $BASE_URL/o/token/ \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "scope=listings:read user:read"

Response

{
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
  "expires_in": 3600,
  "token_type": "Bearer",
  "scope": "listings:read user:read"
}

Building a client with AI

If you are scaffolding the client with an AI coding tool, give it both the schema-level and narrative context so it generates correct requests:

  • OpenAPI specification/api/v1/schema/ for precise endpoint contracts, field types, and request/response structures.
  • Full documentation (Markdown)/full-documentation.md for authentication, behavior details, and usage examples in one file.

Optional: Narrow A Token To One User

Partner apps can request a user-scoped token by adding user_id to the token request. This is useful when your system manages multiple Beyond users and you want a token that can only act on one of them.

curl -X POST $BASE_URL/o/token/ \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "scope=listings:read user:read" \
  -d "user_id=42"

The response includes user_id when the token is narrowed successfully.

Token Tiers And require_user_scoped_tokens

Beyond classifies scopes into tiers. These tiers decide whether a scope can be used on an application-level token, a user-scoped token, or both.

Tier Scopes How to request Behavior
App-level user:write Omit user_id. Operates on the application as a whole. Rejected if you include user_id.
User-level listings:read, listings:write, reservations:read, accounts:read, insights:read Include user_id when user-scoped tokens are required for your application. Acts only on the bound user's resources. If require_user_scoped_tokens is disabled, these scopes may also be used without user_id for application-level access.
Cross-tier user:read Omit or include user_id. Without user_id, reads users owned by the application. With user_id, reads only the bound user.

When require_user_scoped_tokens is enabled for your application, token requests without user_id can still use app-level and cross-tier scopes (user:write, user:read), but not user-level scopes. Requests with user_id can use user-level and cross-tier scopes, but never user:write.

Optional: Narrow A User-Scoped Token To One Credential

If you want the token to behave exactly like one login credential within the user, add credential_id. When omitted, Beyond uses the user's primary credential by default.

curl -X POST $BASE_URL/o/token/ \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "scope=listings:read user:read" \
  -d "user_id=42" \
  -d "credential_id=314"

When credential_id is present, listing visibility and write access are constrained by that credential's global permissions and grants.

Credential-scoped visibility rules

Once a token is bound to a credential, every endpoint that supports user-scoped tokens applies the rules below. The rules are identical for listings and managed accounts: managed accounts are narrowed only when at least one of their listings would also be narrowed.

credential_id present Credential global_permissions What the token can see and do
No (app-level token) n/a All resources owned by every user of the application.
Yes ADMIN All listings and managed accounts owned by the bound user. GET /users/<id>/credentials/ returns every non-deleted credential. Can read resources and use listing write endpoints.
Yes EDIT All listings and managed accounts owned by the bound user. GET /users/<id>/credentials/ returns only the acting credential. Can read resources and use listing write endpoints.
Yes VIEW Same visibility as EDIT, but listing write endpoints return 403 Forbidden.
Yes NONE Only listings explicitly granted to the credential; managed accounts are filtered to those that own at least one granted listing. GET /users/<id>/credentials/ returns only the acting credential.

Soft-deleting a credential (for example, when a user removes a login) revokes the credential for API purposes: any token bound to it will start returning 403 Forbidden immediately, and new token requests that resolve to a soft-deleted credential are rejected at /o/token/.

Make Your First API Call

curl -X GET "$BASE_URL/api/v1/listings/?page[size]=5" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Accept: application/vnd.api+json"

End-to-End Onboarding Flow

Once your OAuth2 application has been provisioned, follow this flow to take a partner's user from creation to a listing that Beyond Pricing is actively pricing. It focuses on the order of operations and the background sync lifecycle, and links to the endpoint pages that document request details.

  1. Get an application-level token
  2. Create a user
  3. Add an account for that user
  4. Get a user-scoped token for that user
  5. Wait for the background sync to finish
  6. List the user's listings and map Beyond Pricing listing IDs to your listing IDs
  7. Enable the listing so the integration framework will begin pushing prices to the account
sequenceDiagram
    participant Partner as PartnerSystem
    participant BP as BeyondPricing

    Partner->>BP: Get app-level token
    Partner->>BP: Create user
    BP-->>Partner: Return user_id
    Partner->>BP: Add account for user
    BP-->>Partner: Queue sync
    Partner->>BP: Get user-scoped token for user
    loop Until sync completes
        Partner->>BP: List accounts for user
        BP-->>Partner: sync-status = queued/in_progress/completed
    end
    Partner->>BP: List user's listings with user-scoped token
    BP-->>Partner: listing id + channel-listings[].channel-id
    Partner->>BP: Update listing activation
    BP-->>Partner: Price syncing enabled

Step 1: Get an App-Level Token

Start with an application-level token so you can create the user and add the user's account. See Get An Access Token above for the client credentials request.

Note

In this onboarding flow, user and account creation use an app-level token with user:write. After the account is created, request a user-scoped token for that user so you can poll account status with user:read and retrieve listings with listings:read.

Step 2: Create a User

Create the partner's user first. The user is the container for the account and for the listings that will later appear in Beyond Pricing.

Use the Create User endpoint details for the request and response schema.

Step 3: Add an Account for the User

After the user exists, add the partner's channel or PMS account for that user. This is the step that starts the import process for listings and reservation history.

Use the Add Account endpoint details for channel credentials, supported integrations, and response behavior.

Step 4: Get a User-Scoped Token

After the account exists, request a user-scoped token for that user. Use this token for user-specific reads in the remaining steps of the onboarding flow.

For collection endpoints such as List Listings, a user-scoped token automatically limits the response to the bound user, so you do not usually need to add filter[owner]={user_id}.

Step 5: Wait for the Background Sync

After the account is created, Beyond Pricing starts a background sync that fetches reservation history for the listings associated with that account. This can take some time, especially for accounts with many listings or a large history.

Check the account's sync-status by polling /api/v1/users/{user_id}/accounts with the List Accounts endpoint until the state reaches completed.

{
  "sync-status": {
    "state": "completed",
    "last-successful-sync-at": "2026-03-06T11:00:00+00:00"
  }
}

Warning

Do not try to map listings or enable price syncing before the account sync has finished. Until sync is complete, the listing set may still be incomplete.

Step 6: Map Beyond Pricing Listing IDs to Your Listing IDs

Once the sync has completed, retrieve listings with the List Listings endpoint using the user-scoped token for that user. The response is already limited to that user's listings.

The Beyond Pricing listing ID is the top-level resource id. Your listing ID from the connected channel or PMS is available in channel-listings[].channel-id.

{
  "id": "12345",
  "channel-listings": [
    {
      "channel": "hostaway",
      "channel-id": "external-listing-987"
    }
  ]
}

See the Listings endpoint reference for filtering behavior, and the JSON:API guide for collection query conventions.

Step 7: Enable a Listing

Listings are created disabled on the Beyond Pricing side. After you have mapped the listing IDs, enable the listing so Beyond Pricing can start pushing prices to the connected account.

Use the Listing Activation endpoint reference for the activation payload and response shape.

Note

After a listing is activated, change its nightly base price through the Base Price customization endpoint. The base price is the anchor used by Beyond Pricing's algorithm, so keeping it accurate ensures recommended prices stay aligned with the partner's expectations.

After Activation

After a listing has been enabled, Beyond Pricing begins the normal price-syncing lifecycle for that listing.

If you need to inspect the listing again after activation, use the Get Listing Details endpoint. For API-wide error semantics, see Error Handling.

Security Notes

  • Request only the scopes your integration needs.
  • If Beyond has configured an IP allowlist for your application, the same IP checks apply to both /o/* and /api/v1/*.
  • user:write is app-level only and cannot be combined with user_id.
  • When require_user_scoped_tokens is enabled, request a user-scoped token with user_id for listings:read, listings:write, reservations:read, accounts:read, and insights:read.
  • user:read is cross-tier: application-level tokens read all users owned by the app; user-scoped tokens read only the bound user.
  • User-scoped tokens inherit the selected credential's permissions. A credential with limited listing grants will see and modify only the listings it is allowed to access.

Common Pitfalls

  • Using the wrong token type. User and account creation require an app-level token, while listing retrieval is expected to use a user-scoped token for the target user. See Narrow A Token To One User.
  • Starting listing mapping too early. Wait until account sync-status is completed.
  • Confusing Beyond Pricing listing IDs with external channel or PMS listing IDs. Use the listing resource id for Beyond Pricing and channel-listings[].channel-id for your external identifier.
  • Forgetting that field names are dasherized in API payloads. See JSON:API Format.

Next Steps