Guide

Zuvo Partner Integration Guide

Integrate Zuvo with your platform or product.

This guide assumes you have already followed the Build a Zuvo Integration guide and have a working OAuth client.

When a Zuvo user clicks the Install Integration button in the Dashboard, they are redirected to your system to begin the OAuth flow. You can implement this redirect in one of two ways:

  • Redirect: Easier to build, but your system cannot verify that the incoming user was sent by Zuvo.
  • Signed redirect: More work to build, but cryptographically verifies that the redirect originated from Zuvo. Recommended for production integrations.

Pick the method that fits your security requirements, then follow the matching section below.

Method 1: Redirect

In this method, you implement a single GET endpoint. Zuvo redirects the user to this endpoint when they click Install Integration, and your endpoint kicks off the OAuth flow.

sequenceDiagram
  autonumber
  participant User
  participant Browser
  participant Partner as Partner (OAuth Client)
  participant Zuvo as Zuvo (OAuth Authorization Server/Protected Resource)

  Note over Browser: Zuvo Studio Open

  User->>Browser: Clicks "Install Integration"

  Browser->>Partner: "Connect to Partner" Click Handler Page
  Partner->>Browser: Redirect to Zuvo Authorization Page

  Browser->>Zuvo: Request Authorization
  Zuvo->>Browser: Redirect to Consent Screen

  Browser->>User: Display Consent Screen
  User->>Browser: Gives Consent

  Browser->>Zuvo: Submit User Consent
  Zuvo->>Browser: Redirect to Partner With Authorization Code

  Browser->>Partner: Submit Authorization Code

  Partner->>Zuvo: Exchange Authorization Code for Token
  Zuvo->>Partner: Return Token

  Partner->>Zuvo: Request Management API Resources
  Zuvo->>Partner: Return Resources

  Partner->>Browser: Ok 200, OAuth Flow Complete

  Browser->>User: Display "Integration Installed" Message

The user clicks Install Integration in the Zuvo Studio, which routes them through the partner's click-handler page and on to the Zuvo authorization page. Zuvo shows a consent screen. Once the user consents, Zuvo redirects back to the partner with an authorization code. The partner exchanges that code for a token, uses the token to request Management API resources, and finally shows the user an "Integration Installed" message.

Step 1: Implement the redirect endpoint

Expose a GET endpoint at any URL you control:

GET https://<your-host>/<optional-path>?project_id=<supabase-project_ref>&organization_slug=<supabase-org-slug>

Zuvo will append the following query parameters to the URL when redirecting:

ParamDescription
project_idZuvo project ref of the project where the user clicked the Install Integration button.
organization_slugZuvo organization slug where the user clicked the Install Integration button.

Save these parameters in your system. You can use them to fetch project or organization details, or to pre-select a project or organization in your UI once the OAuth flow is complete.

Your endpoint may ask the user to sign up, sign in, or perform other setup tasks on your website. Once those are complete, immediately redirect to the Zuvo authorization URL without further user interaction. This starts the OAuth flow.

Step 2: Share your endpoint with Zuvo

Send Zuvo the URL of your endpoint so we can configure the Install Integration button to redirect there.

Method 2: Signed redirect

In this method, Zuvo signs a JWT before redirecting the user. You verify the signature, generate a one-time redirect record, and return its URL to Zuvo. Zuvo then redirects the user to that URL. This guarantees that any redirect your system handles originated from Zuvo.

You will implement two endpoints:

  1. A POST endpoint that validates the signed JWT and returns a unique redirect URL.
  2. A GET endpoint that handles the user once they are redirected to that URL.
sequenceDiagram
  autonumber
  participant User
  participant Browser
  participant Partner as Partner (OAuth Client)
  participant Zuvo as Zuvo (OAuth Authorization Server/Protected Resource)

  Note over Browser: Zuvo Studio Open

  User->>Browser: Clicks "Install Integration"

  Browser->>Zuvo: Request Redirect URL Generation
  Zuvo->>Partner: Send Signed JWT
  Partner->>Partner: Validate JWT
  Partner->>Partner: Generate Unique Redirect URL
  Partner->>Zuvo: Return Redirect URL
  Zuvo->>Browser: Redirect to the Redirect URL

  Browser->>Partner: Visit Redirect URL
  Partner->>Partner: Validate Redirect Record
  Partner->>Browser: Optional User Actions
  Browser->>User: User Performs Optional Actions
  User->>Browser: User Optional Actions Complete
  Browser->>Partner: User Optional Actions Complete
  Partner->>Browser: Redirect to Zuvo Authorization Page

  Browser->>Zuvo: Request Authorization
  Zuvo->>Browser: Redirect to Consent Screen

  Browser->>User: Display Consent Screen
  User->>Browser: Gives Consent

  Browser->>Zuvo: Submit User Consent
  Zuvo->>Browser: Redirect to Partner With Authorization Code

  Browser->>Partner: Submit Authorization Code

  Partner->>Zuvo: Exchange Authorization Code for Token
  Zuvo->>Partner: Return Token

  Partner->>Zuvo: Request Management API Resources
  Zuvo->>Partner: Return Resources

  Partner->>Browser: Ok 200, OAuth Flow Complete

  Browser->>User: Display "Integration Installed" Message

Walking through the sequence: when the user clicks Install Integration, Zuvo sends the partner a signed JWT and asks it to generate a redirect URL. The partner validates the JWT, generates a unique redirect record and URL, and returns it. Zuvo redirects the user to that URL; the partner validates the redirect record, optionally has the user complete extra steps, and then sends them to the Zuvo authorization page. From there the flow matches Method 1: the user consents, Zuvo returns an authorization code, the partner exchanges it for a token, requests Management API resources, and the integration completes.

Step 1: Exchange public keys with Zuvo

Zuvo generates two key-pairs, one for staging, one for production, and shares the public keys with you. Save both public keys and their key IDs in your system. The keys are PEM-encoded EC P-256.

Example:

===============Staging==================

Key ID: pik_3038669348a3ea75dbaf0655
Public Key:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnj3NmwrLPPH/3isvpS601ndQP9Mk
zqppdLDV9YfmoF4wavTyb9UTVE5pJ0fukpo5aOoNb4fBZgESsedIUoEn8Q==
-----END PUBLIC KEY-----

==============Production================

Key ID: pik_89e80ddbca9df41b97e28986
Public Key:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEWCGhwtFWn4jpWZNeyZpTlaAdq/tD
/yBaN0gFPpS8LTFiCPFgnWKbVe3RfExXh7bEhcrEUdWycmYvwrNklWWHRA==
-----END PUBLIC KEY-----

Look up the correct public key by the kid field in the JWT header.

Storing keys by ID enables zero-downtime key rotation. When Zuvo rotates keys, we share new key-pairs and start signing JWTs with the new key ID. Your system picks the correct key based on kid without any code changes.

Step 2: Implement the redirect record endpoint

This endpoint receives the signed JWT from Zuvo and returns a one-time redirect URL.

Host the endpoint at any URL and path you control. Do not require authentication on this endpoint, but apply rate limiting to prevent abuse.

POST https://<your-api-host>/<your-api-path>
Content-Type: application/json

Request body

{
  "token": "<signed-jwt>"
}

JWT fields

The token is a JWT signed with the ES256 private key.

Protected header (JOSE header)

FieldRequiredDescription
algYesAlways ES256 — the only signing algorithm currently supported.
kidYesThe key ID identifying the key pair. Use this to pick the correct public key when verifying the signature.

Payload (claims)

ClaimRequiredDescription
issYesAlways supabase.
audYesA unique string identifying the audience of this JWT. Usually a URL.
iatYesIssued-at timestamp (seconds since epoch).
expYesExpiry timestamp — at most 5 minutes after iat.
organization_slugNoThe Zuvo organization the user is connecting from. Use to pre-select the org during the OAuth consent screen.
project_idNoThe Zuvo project ref the user wants to connect. Use to pre-select a Zuvo project in your UI.

Signature

The header and claims are signed with the EC P-256 private key.

Validation

When you receive a request:

  1. Read the kid field from the JWT header and look up the matching public key.
  2. Verify the JWT signature with that public key.
  3. Verify that alg is ES256.
  4. Verify that iss is supabase.
  5. Verify that aud matches the value you agreed with Zuvo.
  6. Verify that the current time is between iat and exp.

If any check fails, return 401 Unauthorized.

If validation succeeds, generate a UUID to identify this redirect record (also called an integration record), save it in your system with an expiry (typically 1 hour), and return it in the response. The expiry prevents records from accumulating and limits the window in which a leaked record can be used.

Response body

{
  "integrationId": "<a unique uuid>",
  "redirectUrl": "https://<your-api-host>/<your-api-path>/<integration-id>",
  "expiresAt": "<timestamp>"
}
FieldDescription
integrationIdA UUID uniquely identifying the redirect record.
redirectUrlThe URL the user will be redirected to. Must contain the integrationId somewhere in its path so you can retrieve the record on redirect.
expiresAtThe time when the redirect record expires (typically 1 hour from creation). The user must begin the flow before this time.

Step 3: Implement the redirect handler endpoint

This is the GET endpoint at the redirectUrl you returned in the previous step. The redirect record's UUID must be in its path.

When a user arrives at this endpoint:

  1. Extract the redirect record UUID from the URL path.
  2. Look it up in your system. If it doesn't exist or has expired, return 401 Unauthorized.
  3. Optionally, walk the user through any setup required on your side — for example, signing up, signing in, or configuring your system so the integration will work.
  4. Redirect the user to the Zuvo authorization URL to start the OAuth flow.

Step 4: Share your details with Zuvo

Send Zuvo the following so we can configure the Install Integration button:

  • The URL of your redirect record endpoint (Step 2).
  • The URL pattern of your redirect handler endpoint (Step 3).
  • The aud claim value you want Zuvo to send in the signed JWT.

Ask Zuvo for the public keys and key IDs for the staging and production environments.