> **Source:** https://knowledge.leegality.com/document-execution/api/v4-authentication > **Site:** Leegality Knowledge Base — https://knowledge.leegality.com > **About:** Leegality is a document execution platform covering eSigning, stamps, NeSL, workflows, and REST API integration. > **Navigation:** Every article on this site has a plain-text version at `.txt` (this format). To get an index of all articles with their `.txt` links, read: https://knowledge.leegality.com/llms.txt > **AI Guide:** For instructions on how to navigate this knowledge base as an AI agent, read: https://knowledge.leegality.com/ai-readable.txt --- # v4 Authentication (OAuth 2.0) The v4 Workflow APIs use the **OAuth 2.0 Authorization Code** flow. In short: your application sends the user to Leegality to sign in, receives an authorization **code**, exchanges that code for an **access token**, and then calls the v4 APIs with that token. ## How the flow works ```mermaid sequenceDiagram actor User as User participant App as Your application participant Auth as Leegality Authorization Server participant API as Leegality v4 API User->>App: 1. Clicks "Sign in with Leegality" App->>Auth: 2. Redirects the browser to /oauth2/authorize Auth-->>User: 3. Shows the Leegality login page User->>Auth: 4. Signs in and approves access Auth-->>App: 5. Redirects back to your app with ?code=… App->>Auth: 6. POST /oauth2/token (code + Client ID/Secret) Auth-->>App: 7. Returns an access token App->>API: 8. Calls the v4 API with the access token API-->>App: 9. Returns the data App-->>User: 10. Shows the result ``` ## Authorization endpoints All OAuth endpoints are served under the base URL `https://api-gateway.leegality.com/auth`. On sandbox, the base URL is `https://sandbox-gateway.leegality.com/auth`. ## Step 1 — Create an OAuth client Create an OAuth client in the dashboard. This gives you the **Client ID** and **Client Secret** your application uses to obtain access tokens. ![Access the UAM portal from the dashboard](https://knowledge.leegality.com/img/access_uam_panel.png) 1. Log in to the [Leegality dashboard](https://dashboard.leegality.com/sign-in). 2. Click the gear (settings) ⚙️ icon in the top-right corner. 3. In the left menu, go to **Settings → API**. 4. Click **Manage Access Token**. You're redirected to the UAM portal login page. 5. Log in to the UAM portal. 6. Open **OAuth Clients**. 7. Click **+ Create Client** and provide: - **Client Name** — any name to identify this client. - **Grant Type** — choose **Authorization Code**. - **Redirect URLs** — the URL(s) Leegality is allowed to send the user back to after they sign in (carrying the authorization code). The `redirect_uri` you send in Step 2 must **exactly match** one of these values. Add only URLs your application controls. - **Access Token Validity** — how long an access token stays valid, in seconds. - **Refresh Token Validity** — how long a refresh token stays valid, in seconds. 8. Click **Create Client**. The **Client ID** and **Client Secret** created successfully. > **Warning — Copy your Client Secret now** > > The Client Secret is shown only once. Copy and store both the Client ID and Client Secret before closing the window. ## Step 2 — Get an authorization code Redirect the user's browser to the authorization endpoint: > **Info — Sandbox Endpoint** > > `https://sandbox-gateway.leegality.com/auth/oauth2/authorize` Include the query parameters shown below: ``` GET https://api-gateway.leegality.com/auth/oauth2/authorize?response_type=code&client_id=&redirect_uri=&scope=*&state= ``` | Parameter | Required | Description | | --- | --- | --- | | `response_type` | Yes | Must be `code`. | | `client_id` | Yes | Your client's ID from Step 1. | | `redirect_uri` | Yes | Where to send the user after they sign in. Must **exactly match** a Redirect URL registered on the client. | | `scope` | Yes | The access being requested. Use `*`. | | `state` | Recommended | An opaque value your application generates. Leegality returns it unchanged, so you can confirm the response belongs to your request (protects against CSRF). Use a **different value for every authorization request**. | The user sees the Leegality login page, signs in, and approves access. Leegality then redirects the browser back to your `redirect_uri` with the authorization code appended: ``` ?code=&scope=*&state= ``` Your application reads the `code` value from the query string in its redirect handler. > **Warning — Use each code once** > > The authorization code is single-use and short-lived. Exchange it for a token immediately (Step 3) and **never retry the same code** — replaying a code invalidates the tokens issued from it. ## Step 3 — Exchange the code for an access token From your backend, exchange the code for an access token at the token endpoint. Authenticate with your Client ID and Secret using **HTTP Basic** auth. > **Info — Sandbox Endpoint** > > `https://sandbox-gateway.leegality.com/auth/oauth2/token` ```bash curl --location 'https://api-gateway.leegality.com/auth/oauth2/token' \ --header 'Authorization: Basic ' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'grant_type=authorization_code' \ --data-urlencode 'code=' \ --data-urlencode 'redirect_uri=' ``` | Field | Where | Description | | --- | --- | --- | | Client ID + Secret | `Authorization: Basic` header | Base64-encode `client_id:client_secret`. Most HTTP clients build this header for you when you supply a username and password. Credentials must go **here**, not in the body. | | `grant_type` | Body | Must be `authorization_code`. | | `code` | Body | The authorization code from Step 2. | | `redirect_uri` | Body | The same value you used in Step 2. | A successful response returns the access token: ```json { "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6ImF0K2p3dCJ9...", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6InJ0K2p3dCJ9...", "scope": "*" } ``` The access token is valid for the number of seconds shown in `expires_in`. ## Step 4 — Call the v4 APIs Send the access token in the `Authorization` header (as a Bearer token) on every v4 API request: ```bash curl --location 'https://app1.leegality.com/api/v4/packs/search?max=3' \ --header 'Authorization: Bearer ' ``` When the token expires, use the refresh token to get a new one (Step 5) — no need to send the user through sign-in again. ## Step 5 — Refresh the access token When the access token expires, use the `refresh_token` from Step 3 to get a new one, without sending the user through sign-in again. Call the **same** token endpoint with `grant_type=refresh_token`. ```bash curl --location 'https://api-gateway.leegality.com/auth/oauth2/token' \ --header 'Authorization: Basic ' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'grant_type=refresh_token' \ --data-urlencode 'refresh_token=' ``` | Field | Where | Description | | --- | --- | --- | | Client ID + Secret | `Authorization: Basic` header | Same as Step 3. | | `grant_type` | Body | Must be `refresh_token`. | | `refresh_token` | Body | The `refresh_token` from the Step 3 response. | The response has the same shape as Step 3, with a fresh `access_token`. ## Rules to know > **Note** > > - **Redirect URI must match exactly.** The `redirect_uri` in Steps 2 and 3 must be identical to a Redirect URL registered on the client — same scheme, host, and path. > - **Use `127.0.0.1`, not `localhost`.** `localhost` is rejected as a redirect host; use the loopback IP for local testing. > - **Client credentials go only in the `Authorization: Basic` header** at `/oauth2/token`. Sending them in the request body is rejected. > - **Authorization codes are single-use.** Never retry a code exchange — start the flow again to get a new code.