Have your sandbox credentials handy
During onboarding you’ll have received:
client_id(e.g.ywc_a1b2c3d4)client_secretwebhook_secret(only if you registered a webhook URL)- One or more registered
redirect_uris
Generate a PKCE pair
Every authorization request needs a fresh Store the
code_verifier /
code_challenge pair. The verifier stays in your server; the challenge
goes on the wire. See Authentication for samples
in other languages.code_verifier against the user’s session — you’ll need it in
step 4.Send the crew member to /oauth/authorize
Build this URL and redirect the user’s browser to it. The DSS dashboard
handles sign-in and shows them a consent screen listing the scopes you
requested. On approval they’re redirected back to your
redirect_uri
with a one-shot code and the state you passed.Exchange the code for tokens
The user’s browser hits your Response:Store the tokens against the user record on your side. The
redirect_uri with ?code=...&state=....
Your server exchanges the code for an access token + refresh token.refresh_token rotates on every use — when you refresh, swap the stored
value for the new one immediately. See
Authentication / refreshing.What to build next
In rough order of value:- Render the data in your UI. Pull
/v1/me/sea-timefor the dashboard totals and/v1/me/vesselsfor the history list. Each returnsrecord_updated_atand supports conditional GETs — use them. - Wire conditional GETs. Cache the
ETagand replay it on the next request asIf-None-Match. A304costs you nothing against your rate limit budget beyond a single round trip. - Register a webhook URL so you don’t have to poll. See Webhooks.
- Add the disconnect path. Call
POST /oauth/revokewith the user’s token when they want to disconnect from your side (revoking one token revokes the whole pair), and handleuser.consent.revokedwebhooks for when they disconnect from ours.
Common gotchas
invalid_grant on token exchange
invalid_grant on token exchange
Three causes account for ~all of these. The authorization code expired
(60-second TTL — exchange immediately), the code was already used (codes
are single-use), or the
redirect_uri you passed at token exchange
doesn’t exactly match the one you passed at authorize. Trailing slashes
count.invalid_token after a few hours
invalid_token after a few hours
Access tokens are 1-hour TTL. Refresh them with
grant_type=refresh_token. The previous access + refresh pair is revoked
atomically when you refresh — if you keep using the old refresh token,
you’ll lose the connection and the user will have to reconsent.
See Authentication / refreshing.insufficient_scope
insufficient_scope
Your access token was issued without the scope this endpoint needs. Send
the user back through the authorize flow with the missing scope
requested. Refresh cannot widen scope by design.

