JLS
Developer Docs

Quick Start

Get your app connected to JLS Crewbook in 7 steps.

1

Get your API key

Go to the API Keys page in your dashboard to create a read-scope API key. You’ll receive two values: a Client ID (UUID) used as client_id in OAuth requests, and a secret key used in the x-api-key header. Keep the secret safe — treat it like a password. The Client ID can always be found later via View Details. (Need an admin-scope key? Contact your EDS administrator.)

2

Register a redirect URI

On the API Keys page, click View Details on your API key and add the exact callback URL your app will use (e.g. https://yourapp.com/auth/callback). The redirect URI must match exactly during the OAuth flow — including scheme, host, path, and trailing slash.

3

Redirect to authorize

When an employee wants to log in, redirect their browser to the EDS authorize endpoint. Include your Client ID (from View Details), redirect_uri, and a random state value for CSRF protection.

const state = crypto.randomUUID();
sessionStorage.setItem("oauth_state", state);

const params = new URLSearchParams({
  // Client ID (UUID) from your API key's View Details — NOT the secret key
  client_id: "YOUR_CLIENT_ID",
  redirect_uri: "https://yourapp.com/auth/callback",
  state,
});

window.location.href = `https://<your-eds-host>/api/v1/oauth/authorize?${params}`;
4

Handle the callback

EDS redirects back to your app with a short-lived code and the state you sent. Verify the state matches, then exchange the code for a session token.

// In your callback route handler
const params = new URLSearchParams(window.location.search);

if (params.get("error") === "access_denied") {
  // Employee denied consent or account is inactive
  throw new Error(params.get("error_description") ?? "Access denied");
}

const code = params.get("code");
const returnedState = params.get("state");
const savedState = sessionStorage.getItem("oauth_state");

if (!code || returnedState !== savedState) {
  throw new Error("Invalid OAuth callback");
}

sessionStorage.removeItem("oauth_state");
5

Exchange code for session token

POST the authorization code to /api/v1/oauth/token within 5 minutes. Include your API key in the x-api-key header. You’ll receive a 24-hour session token and the authenticated employee’s profile.

const response = await fetch(`https://<your-eds-host>/api/v1/oauth/token`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": "YOUR_API_KEY",
  },
  body: JSON.stringify({
    grant_type: "authorization_code",
    code,
    redirect_uri: "https://yourapp.com/auth/callback",
  }),
});

const { session_token, employee, expires_at } = await response.json();
// Store session_token securely (e.g. httpOnly cookie)
6

Use the session token

On subsequent requests, verify the session is still active by calling /api/v1/oauth/introspect. This returns the employee object if the token is valid.

const response = await fetch(`https://<your-eds-host>/api/v1/oauth/introspect`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": "YOUR_API_KEY",
  },
  body: JSON.stringify({ session_token: "SESSION_TOKEN" }),
});

const data = await response.json();

if (!data.active) {
  // Token is expired or revoked redirect to login
  redirectToLogin();
}

const employee = data.employee; // Use employee data
7

Log the user out

When an employee logs out of your app, revoke their session token so EDS invalidates it. This endpoint is idempotent — calling it on an already-revoked token is safe.

await fetch(`https://<your-eds-host>/api/v1/oauth/revoke`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": "YOUR_API_KEY",
  },
  body: JSON.stringify({ session_token: "SESSION_TOKEN" }),
});

// Clear local session state
sessionStorage.clear();