Authentication
Get credentials
Vysual registers your app and sends you two values:
| Value | Notes |
|---|---|
client_id | Public identifier, for example your-app. |
client_secret | Shown once. Keep it on your server; never ship it to a browser or mobile app. |
Send us these when registering:
- App name, shown to users on the consent screen.
- Logo URL: an
https://link to a square PNG or SVG you host, at least 128×128. It appears on the consent screen and in the user’s Connected Apps list. Tell us if it changes. - Website URL.
- Redirect URIs: one or more, matched exactly. Must be
https://;http://localhostis allowed for testing.
Connect flow
- Your app: the user clicks Connect Vysual and you redirect to
/oauth/authorize. On Vysual, the user signs in, picks companies, and clicks Allow access. - Your app: the callback receives
?code=…&state=…. Your server exchanges the code atPOST /api/oauth/token. - Your server: calls
GET /api/v1/…with the Bearer token.
Send the user to Vysual
Generate a PKCE pair: code_verifier is 43–128 random URL-safe characters, and code_challenge is BASE64URL(SHA256(code_verifier)). Store the verifier and a random state with the user’s session.
https://app.vysual.com/oauth/authorize
?response_type=code
&client_id=YOUR_CLIENT_ID
&redirect_uri=https%3A%2F%2Fyourapp.com%2Foauth%2Fvysual%2Fcallback
&state=RANDOM_STATE
&code_challenge=CODE_CHALLENGE
&code_challenge_method=S256
Handle the callback
- Approved:
…/callback?code=vyc_…&state=RANDOM_STATE - Cancelled:
…/callback?error=access_denied&state=RANDOM_STATE
Always check that state matches what you stored. The code works once and expires after 10 minutes.
Exchange the code for tokens
POST /api/oauth/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic base64(client_id:client_secret)
grant_type=authorization_code
&code=vyc_…
&redirect_uri=https://yourapp.com/oauth/vysual/callback
&code_verifier=YOUR_CODE_VERIFIER
client_id and client_secret can go in the body instead of the Basic header. JSON bodies are accepted too.
{
"access_token": "vya_…",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "vyr_…",
"scope": "assets:read"
}
Tokens
Every credential has a prefix, so you can tell them apart in logs.
| Prefix | What it is | Lifetime |
|---|---|---|
vyc_ | Authorization code | 10 minutes, works once |
vya_ | Access token (Bearer) | 1 hour |
vyr_ | Refresh token | Until used; replaced on every refresh |
vys_ | Client secret | Until Vysual rotates it |
Refresh
Refresh tokens rotate: each refresh returns a new refresh token and the old one stops working. Store the new one every time.
POST /api/oauth/token
Authorization: Basic base64(client_id:client_secret)
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token&refresh_token=vyr_…
A 400 invalid_grant means the connection has ended: the user disconnected it in Vysual or lost access. Mark it as disconnected and ask the user to connect again.
Disconnect
When a user disconnects Vysual in your app, revoke the connection:
POST /api/oauth/revoke
Authorization: Basic base64(client_id:client_secret)
Content-Type: application/x-www-form-urlencoded
token=vyr_…
This always returns 200 {}. Users can also disconnect your app from their Vysual profile. After that, your next API call gets a 401 and your next refresh gets invalid_grant.