Connected Apps Partner Guide

Let players securely connect their PB Vision account to your product.

PB Vision Connected Apps allow approved products to request permission to read a player's PB Vision data. Players sign in through PB Vision, review the access your app is requesting, and can disconnect the app at any time.

This guide explains what Connected Apps provide, how to request credentials, and how to implement the authorization flow.

Looking to send video into PB Vision for processing and receive results through a webhook? See the PB Vision API Partner Guide. Connected Apps and the Partner API are separate integrations, although a product may use both.


Who Connected Apps Are For

Connected Apps are designed for products that add value to an existing PB Vision player's account and data. Common use cases include:

  • Coaching and player-development apps

  • Analytics dashboards and training tools

  • Community and social products

  • League, club, and facility software

  • Desktop and mobile tools for reviewing player performance

See examples and learn more at https://pb.vision/apps.


Connected Apps vs. the Partner API

Use Connected Apps when a player should sign in and authorize your product to read data from their PB Vision account.

Use the Partner API when your product needs to upload video into PB Vision for processing, receive completion webhooks, or manage an automated video-analysis workflow.

Connected App credentials do not enable Partner API uploads or webhooks, and a Partner API key does not replace user authorization. A product may use both integrations. If your product needs both capabilities, let us know when you request access.


Available Access

Your app should request only the scopes it needs. The player sees each requested scope on the PB Vision consent screen.

ScopeAccess providedEndpoint

library:read

Read the player's PB Vision video library, including folders, video metadata, and media handles

POST /library/get

trends:read

Read the player's per-game trend data, ratings, and stats

POST /trend/get

referrals:read

Read the referral code the player originally used, when one exists

POST /user/referrals/get

You can retrieve the current scope list without authentication:

POST https://api-2o2klzx4pa-uc.a.run.app/oauth/scopes

Connected App access is currently read-only. It does not provide unrestricted account access or enable video uploads, processing webhooks, DUPR submissions, or raw per-video insights, stats, or computer-vision exports. Those capabilities use PB Vision's product UI, Partner API, or separately approved export paths.

Eligible new users who connect through your app may also be attributed to your partner account for referral rewards. Referral activity is tracked through your PB Vision Ambassador dashboard.


Request Connected App Access

Start at pb.vision/apps and choose Become a Partner, or contact support@pb.vision. Include:

  • App display name: Shown on the PB Vision consent screen and in the player's Connected Apps settings.

  • Product description: What you are building and how you plan to use PB Vision data.

  • Production redirect URI or URIs: Exact callback URLs, including the full scheme, domain, port, and path. Production web callbacks must use HTTPS. For approved local loopback testing, use http://127.0.0.1/<path>, not http://localhost/<path>.

  • Client type: Confidential or public.

  • Homepage URL: Optional, but recommended.

  • Square icon URL: Optional, but recommended.

  • Development redirect URI: Include this if you also want separate development credentials.

Choose the Correct Client Type

Use a confidential client if your application has a secure backend that can store a client secret and perform the token exchange server-side.

Use a public client if your application cannot securely store a secret, such as a browser-only, desktop, native, or mobile application. Public clients receive a Client ID without a Client Secret and authenticate using PKCE alone.

PB Vision returns a Client ID and, for confidential clients, a Client Secret. Store the Client Secret immediately and securely. Never expose it in browser code, mobile code, desktop binaries, public repositories, logs, or messages that are not encrypted.


Environments

PB Vision can issue separate production and development credentials. The development environment has separate accounts, app registrations, and data. A production registration does not automatically exist in development.

EnvironmentAuthorization URLAPI host

Production

https://pb.vision/oauth/authorize

https://api-2o2klzx4pa-uc.a.run.app

Development

https://pbv-dev.web.app/oauth/authorize

https://api-ko3kowqi6a-uc.a.run.app

Use the credentials issued for the same environment as the authorization and API hosts. Ask PB Vision for development credentials only if your integration needs the isolated development environment.

Local Development

The recommended local callback is an IPv4 loopback URI such as:

http://127.0.0.1:8787/api/pbv/oauth/callback

Register the loopback path with PB Vision. PB Vision ignores the port during loopback matching, so your app may use a fixed port or bind an available ephemeral port at runtime. The path must match. Use the literal 127.0.0.1, not localhost. This avoids requiring local TLS and follows the loopback pattern recommended for installed applications.


OAuth Authorization Flow

1. Generate PKCE and State Values

For each authorization request:

  1. Generate a cryptographically random code_verifier containing 43 to 128 unreserved characters.

  2. Generate code_challenge = BASE64URL(SHA256(code_verifier)).

  3. Generate a cryptographically random state value and associate it with the user's session.

  4. Store the code_verifier temporarily so it can be used during the token exchange.

Only the S256 PKCE method is supported.

2. Send the Player to PB Vision

Redirect the player's browser to:

https://pb.vision/oauth/authorize
  ?client_id=<your Client ID>
  &redirect_uri=<one registered redirect URI>
  &scope=library%3Aread%20trends%3Aread
  &state=<random CSRF token>
  &code_challenge=<PKCE code challenge>
  &code_challenge_method=S256

URL-encode every parameter. Encode spaces between scopes as %20. If a Client ID contains +, encode it as %2B.

The player signs in to PB Vision, reviews the requested permissions, and chooses Allow or Deny.

After approval, PB Vision redirects to:

<your redirect URI>?code=<authorization code>&state=<state>

If the player denies access, PB Vision redirects to:

<your redirect URI>?error=access_denied&state=<state>

Verify that the returned state exactly matches the value stored for that authorization request. Do not continue if it does not match.

The PB Vision account that owns the partner registration may also authorize the app, which can be useful for end-to-end testing.

3. Exchange the Authorization Code

Authorization codes are single-use and expire after 60 seconds. Exchange the code immediately.

Confidential clients should make this request from their backend:

POST https://api-2o2klzx4pa-uc.a.run.app/oauth/token
Content-Type: application/json

{
  "grant_type": "authorization_code",
  "code": "<authorization code>",
  "code_verifier": "<the original PKCE code verifier>",
  "client_id": "<your Client ID>",
  "client_secret": "<your Client Secret>",
  "redirect_uri": "<the same redirect URI used above>"
}

Public clients omit client_secret.

The redirect_uri must exactly match the value used in the authorization request.

A successful response looks like:

{
  "access_token": "pbv_pat_<uid>_<secret>",
  "token_type": "Bearer",
  "scope": "library:read trends:read"
}

The returned scope value is space-separated and shows the access actually granted.

PB Vision access tokens do not currently expire by default, and PB Vision does not issue refresh tokens. Store access tokens securely and continue using them until the player or your app revokes access.

If the same player authorizes the same or a smaller set of scopes again, PB Vision may return the existing token. If the player authorizes additional scopes, PB Vision issues a new token and invalidates the previous token for that app.

4. Call an Authorized Endpoint

Send the access token using the standard Bearer authorization header.

Example: read the player's library.

curl -sS -X POST https://api-2o2klzx4pa-uc.a.run.app/library/get \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{}'

The response includes folders and video entries. The main fields are:

{
  "folders": [
    {
      "fid": 123456789,
      "name": "League Night",
      "epoch": 1784235600
    }
  ],
  "videos": [
    {
      "vid": "abc123def456",
      "name": "Game 1",
      "epoch": 1784235600,
      "secs": 698,
      "fid": 123456789
    }
  ]
}
  • vid is the PB Vision video handle.

  • epoch is when the game was played, or when the upload finished if the game time is unavailable.

  • secs is the video duration in seconds.

  • fid associates a video or session with a folder.

  • Multi-game videos include a sessions array with session-level names, timestamps, durations, and folders. A session may be null when the player is only entitled to some sessions in the video.

  • Optional fields such as hidden, starred, new, and processingWorkflowIds describe the player's library state. Respect hidden videos and sessions rather than presenting them as active library items.

Stream a Library Video

For a production vid, the whole-video media and poster assets are:

Video:     https://storage.googleapis.com/pbv-pro/<vid>/max.mp4
Poster:    https://storage.googleapis.com/pbv-pro/<vid>/poster.jpg
Thumbnail: https://storage.googleapis.com/pbv-pro/<vid>/thumbnail.jpg

Development assets use the pbv-pro-dev bucket instead. max.mp4 is the streamable H.264 file used by the PB Vision player. For a multi-session upload, it contains the complete video rather than a separate file for each session. No additional Connected App scope or Partner API export setting is required to stream this file after library:read returns its vid.

OAuth protects discovery of the player's library. The media asset URLs are not separately OAuth-authenticated, so treat video handles and asset URLs as sensitive bearer-style user data. Do not put them in logs, analytics, public pages, or unrelated user records. If max.mp4 does not return Content-Type: video/mp4, send PB Vision the affected vid without including the player's access token.

Example: read the referral code the player originally used, when one exists.

curl -sS -X POST https://api-2o2klzx4pa-uc.a.run.app/user/referrals/get \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{}'

The response is { "code": "..." } when the player signed up through a referral code, or {} otherwise. This endpoint does not expose the referrer's user ID, rewards, balance, or other referral state.

POST /trend/get accepts a JSON body containing the authorizing player's PB Vision UID:

{
  "forUID": "<PB Vision user UID>"
}

Current access tokens use the format pbv_pat_<uid>_<secret>. The UID is included in the token value for use with this request. Treat the entire token as a credential and do not log or expose it.


Revoking Access

Players can disconnect an app at any time from their PB Vision account settings under Settings > Account > Connected Apps.

Partners can also revoke a token when a player disconnects or removes the integration from the partner product:

POST https://api-2o2klzx4pa-uc.a.run.app/oauth/revoke
Content-Type: application/json

{
  "token": "<access token>",
  "client_id": "<your Client ID>",
  "client_secret": "<your Client Secret>"
}

Public clients omit client_secret.

The revocation endpoint returns 200 whether or not the token was active. After revocation, the player must complete the authorization flow again to reconnect. When a player disconnects, stop all API and media access for that connection and delete stored access tokens plus any cached PB Vision library metadata or asset URLs that are no longer needed.


Public, Native, and Desktop Clients

Applications that cannot protect a Client Secret must be registered as public clients.

  • Public clients use PKCE without a Client Secret.

  • Store access tokens in the operating system's secure credential store.

  • Desktop apps and approved local-development flows may register an http://127.0.0.1 loopback redirect URI.

  • PB Vision ignores the loopback port during matching, allowing the app to bind an available ephemeral port at runtime.

  • Use the literal 127.0.0.1, not localhost, for loopback redirects.

  • Mobile apps should use an HTTPS app or universal link as their production redirect URI.


Security Checklist

  • Generate a new PKCE pair and state value for every authorization request.

  • Verify state before exchanging the authorization code.

  • Keep Client Secrets and access tokens out of source code, URLs, analytics, logs, and support messages.

  • Store confidential-client secrets and access tokens in a secrets manager or encrypted server-side store.

  • Store public-client access tokens in the operating system's secure credential store.

  • Request only the scopes your product needs.

  • Revoke the access token when a player disconnects the integration in your product.

  • Stop fetching media and remove unneeded cached library metadata and asset URLs when the player disconnects.

  • Treat access tokens as credentials even though the current token format includes the PB Vision user UID.


Error Responses

OAuth errors use standard error codes inside PB Vision's response envelope:

{
  "code": "BadRequestException",
  "message": "invalid_grant: PKCE code_verifier does not match code_challenge",
  "data": {
    "error": "invalid_grant",
    "error_description": "PKCE code_verifier does not match code_challenge"
  }
}

Read body.data.error and body.data.error_description when handling an OAuth error.

ErrorCommon cause

invalid_request

Missing parameter or redirect URI mismatch

invalid_client

Unknown Client ID or incorrect Client Secret

invalid_grant

Expired, reused, or mismatched authorization code, PKCE verifier, or redirect URI

invalid_scope

Missing or unknown scope

HTTP 403 from an API endpoint

The token was revoked, lacks the required scope, or the endpoint is not available to Connected App tokens

Never send PB Vision a Client Secret, access token, authorization code, or PKCE verifier in a normal support reply. If you need help troubleshooting, send the request URL or body with sensitive values removed, the HTTP status, and the sanitized error response.


Frequently Asked Questions

Can we receive separate sandbox credentials?

Yes. PB Vision can issue separate credentials for the development environment. Development has separate accounts, registrations, and data. Send us the exact staging callback URI and whether the staging client is confidential or public.

How should we test a local callback?

Register an http://127.0.0.1/<path> loopback callback. PB Vision ignores the port during matching, so you can use a fixed or ephemeral local port. Use 127.0.0.1, not localhost.

Can we register more than one redirect URI?

Yes. Send every exact redirect URI you need registered. Except for supported loopback behavior, scheme, domain, port, and path must match exactly.

Do we need PKCE if we have a Client Secret?

Yes. S256 PKCE is required for both confidential and public clients.

Do access tokens expire?

Access tokens do not currently expire by default. There is no refresh-token flow. Tokens remain valid until revoked.

Can the PB Vision account that owns the app authorize it?

Yes. The partner account that owns the Connected App registration can authorize its own app for testing.

Can we stream videos from the player's library?

Yes. library:read returns each video's vid. Use that handle with the documented max.mp4, poster, and thumbnail paths. Treat the handle and asset URLs as sensitive player data and stop using them if the player disconnects.

Can Connected Apps upload videos or receive processing webhooks?

Not through Connected App access alone. Those workflows use the separately enabled PB Vision Partner API. A product may use both integrations.

How does a player disconnect our app?

The player can open PB Vision account settings, go to Account > Connected Apps, and select Disconnect.

What happens if we request more scopes later?

The player must complete authorization again and approve the expanded scope set. Store the newly returned token because the previous token may no longer be valid.


Additional Resources