Guide

Connecting a partner integration via OAuth 2.1

Let your product request access to a mutual customer's rzilient data through a standard authorization-code flow with PKCE. The customer consents once; you receive a bearer token scoped to that customer's company, usable against every endpoint below under /api/external/v1.

1
Redirect to consent
Send the customer's browser to rzilient with your client_id and a PKCE challenge.
→
2
Customer approves
Their IT manager sees your app name and requested scope, then authorizes.
→
3
Exchange for a token
Trade the returned code for a long-lived, tenant-scoped bearer token.
ⓘ The token you receive is tenant-scoped — it grants access to exactly one customer company (the one whose manager consented). It does not expire and has no refresh token; the customer can revoke it any time from their rzilient settings, and re-consenting automatically rotates it.
1 Register your application

Registration is set up directly on the rzilient platform — either by an admin at your organization who already manages mutual customer companies on rzilient (self-service, from their own account), or by the rzilient team on your behalf if your integration has no rzilient login of its own. Either way, we'll need:

ItemNotes
App nameShown to customers on the consent screen — keep it recognizable to your own users.
Logo URLHTTPS, square, ≥112×112px. Displayed next to your app name at consent time.
Redirect URI(s)HTTPS only, exact match enforced — no wildcards. Send both staging and production if applicable.
Contact emailWhere your one-time credential link will be sent.

You'll receive a secure link — generated on our platform, nothing third-party involved — that shows your client_id and client_secret exactly once. Copy both into your secret manager immediately: the link cannot be reopened, and we cannot retrieve the secret afterward (we store only a hash, the same way a password manager would).

⚠ If the link expires or is lost before you retrieve your credentials, contact your rzilient technical contact for a fresh one — this does not require re-registering your application.
ⓘ New applications undergo a brief internal review (typically same-day) before they appear on any customer's consent screen. You can retrieve your credentials and start building immediately — ask about a sandbox application to test against while review is in progress.
2 Endpoints
PurposeURL
Authorize (browser)https://join.rzilient.club/oauth/authorize
Token exchange (server)https://api.rzilient.tech/oauth/token
Revocation (server)https://api.rzilient.tech/oauth/revoke
External API basehttps://api.rzilient.tech/api/external/v1
3 Step-by-step
0
Generate a PKCE pair — once per authorization attempt

code_challenge_method=S256 is mandatory. Never reuse a verifier across customers or retries.

import { randomBytes, createHash } from 'node:crypto';

const codeVerifier = randomBytes(48).toString('base64url');
const codeChallenge = createHash('sha256').update(codeVerifier).digest('base64url');
require 'securerandom'
require 'openssl'
require 'base64'

code_verifier  = SecureRandom.urlsafe_base64(48)
code_challenge = Base64.urlsafe_encode64(
  OpenSSL::Digest::SHA256.digest(code_verifier), padding: false
)
import secrets, hashlib, base64

code_verifier  = secrets.token_urlsafe(48)
code_challenge = base64.urlsafe_b64encode(
    hashlib.sha256(code_verifier.encode()).digest()
).rstrip(b'=').decode()
1
Redirect the customer's browser
GET
https://join.rzilient.club/oauth/authorize
  ?client_id=YOUR_CLIENT_ID
  &response_type=code
  &redirect_uri=https://yourapp.example.com/integrations/rzilient/callback
  &scope=external_api
  &state=RANDOM_OPAQUE_VALUE
  &code_challenge=CODE_CHALLENGE
  &code_challenge_method=S256
  • redirect_uri must byte-for-byte match a registered URI.
  • state must be unguessable (≥128 bits) and verified on callback — your CSRF defense.
  • Only rzilient company managers/admins can consent.
2
Handle the callback

Success:

https://yourapp.example.com/integrations/rzilient/callback?code=AUTH_CODE&state=RANDOM_OPAQUE_VALUE

Denial or error:

...?error=access_denied&error_description=...&state=RANDOM_OPAQUE_VALUE

Verify state on every callback. The code is single-use and expires in 10 minutes — exchange it immediately.

3
Exchange the code for a token — server to server
cURL
curl -s https://api.rzilient.tech/oauth/token \
  -X POST \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d grant_type=authorization_code \
  -d code=AUTH_CODE \
  -d redirect_uri=https://yourapp.example.com/integrations/rzilient/callback \
  -d client_id=YOUR_CLIENT_ID \
  -d client_secret=YOUR_CLIENT_SECRET \
  -d code_verifier=CODE_VERIFIER
Response
{
  "access_token": "9iHIhNKsrBpYQQr6JwjiLu1ZZz2wVNZtI3SCjmyc7Es=",
  "token_type": "Bearer",
  "scope": "external_api",
  "created_at": 1753257600
}
  • No expires_in, no refresh_token — the token is long-lived by design.
  • The token contains base64 characters (+, /, =). Use only in the Authorization header, never in a URL.
  • Reusing a consumed code invalidates the token issued for it — make your callback idempotent before exchanging.
4
Call the External API
cURL
curl -s https://api.rzilient.tech/api/external/v1/clients \
  -H 'Authorization: Bearer 9iHIhNKsrBpYQQr6JwjiLu1ZZz2wVNZtI3SCjmyc7Es='

Every request is automatically scoped to the customer that consented — there's no tenant parameter, and no way to reach another company with this token. Full endpoint reference below.

4 Multiple customers & revocation

One authorization = one token = one customer company. Key stored tokens by your own customer/workspace identifier, and trigger the flow from a per-customer "Connect rzilient" action in your product.

To revoke programmatically (e.g. a customer disconnects from your side):

cURL
curl -s https://api.rzilient.tech/oauth/revoke \
  -X POST \
  -u 'YOUR_CLIENT_ID:YOUR_CLIENT_SECRET' \
  -d token=ACCESS_TOKEN

Returns 200 regardless of whether the token was valid. After revocation from either side, the token stops working immediately.

5 Error handling
WhereErrorMeaningWhat to do
Callback / consent application_not_active Your application hasn't cleared internal review yet Wait for the confirmation from your rzilient contact; ask about a sandbox app to keep testing meanwhile
Callback access_denied User cancelled or lacks manager role Show "connection cancelled"; offer retry
/oauth/token invalid_grant Code expired, already used, or verifier mismatch Restart from step 1 with fresh PKCE values
/oauth/token invalid_client Bad client_id / client_secret Check credentials; contact us if rotated
External API 401 Token revoked or invalid Mark customer as disconnected; do not retry in a loop
External API 429 Rate limited Back off with jitter; respect Retry-After
6 Security checklist
  • Secrets and tokens live in a secret manager — never in code, logs, or frontend bundles
  • state generated with a CSPRNG and verified on every callback
  • Fresh PKCE pair per authorization attempt; verifier never leaves your server
  • Token exchange and API calls made only over TLS, server-to-server
  • A "Disconnect rzilient" action that calls /oauth/revoke and deletes the stored token
ⓘ Need a sandbox to test against? Ask your rzilient technical contact for a dedicated client_id pointing at your staging redirect URI, plus a demo company with seeded data.