From 7a78d7daac46fb5459b661f71a4085d133ecf4dd Mon Sep 17 00:00:00 2001 From: Mudit Garg <35302867+garg-mudit@users.noreply.github.com> Date: Wed, 4 Feb 2026 14:43:38 +0530 Subject: [PATCH 1/4] TIR - Updated assets/navigator-collection.json --- assets/navigator-collection.json | 4184 ++++++++++++++++++++++++++++-- 1 file changed, 3937 insertions(+), 247 deletions(-) diff --git a/assets/navigator-collection.json b/assets/navigator-collection.json index 1f29ada..fe54078 100644 --- a/assets/navigator-collection.json +++ b/assets/navigator-collection.json @@ -1,46 +1,3635 @@ { + "_": { + "postman_id": "c4b4127d-1d50-42fd-a4d9-4b52efe34171" + }, "item": [ { - "name": "Agreements", - "description": "", + "id": "9130a0bf-4525-468a-b50f-db0eeb394b11", + "name": "🔐 Quick Auth Setup → Then Run APIs", + "description": { + "content": "Use this folder to authenticate with **Docusign** and populate ``{{access_token}}`` (and ``{{refresh_token}}`` when available). All other requests can either inherit **OAuth 2.0** from the collection (UI token) or you can set a request to **Bearer {{access_token}}** to use variable-based auth instead.\n\n### Which flow should I use?\n\n| Flow | When to use | Human present? | Client secret? |\n| --- | --- | --- | --- |\n| **Confidential Auth Code** | Server apps that can store a secret; supports refresh tokens | Yes | **Yes** |\n| **Public Auth Code (PKCE)** | SPA/mobile or apps that **cannot** store a secret | Yes | No (uses PKCE) |\n| **JWT (Service Integration)** | Server/daemon jobs acting for a user after one-time consent | No (after consent) | No (needs private key) |\n\n**Prerequisites**\n- ``{{authServer}}`` → `https://account-d.docusign.com` (Developer) or `https://account.docusign.com` (Prod)\n- ``{{redirectUri}}`` registered on your Integration Key\n- ``{{scope}}`` (typical: `signature`; add `impersonation` for JWT; `extended` for rolling refresh)\n- IDs/secrets: ``{{integrationKey}}``, ``{{clientSecret}}`` (confidential), ``{{publicIntegrationKey}}`` (PKCE), ``{{userId}}`` & ``{{privateKey}}`` (JWT)\n\n**Run the flows**\n1) *Confidential Auth Code*: Open **02-1 Helper** → sign in & copy `?code` → set ``{{authCodeNoPkce}}`` (env or collection) → run **02-2 Exchange**.\n2) *Public Auth Code (PKCE)*: Open **03-1 Helper** → sign in & copy `?code` → set ``{{authCodePkce}}`` (env or collection) → run **03-2 Exchange**.\n3) *JWT*: Ensure consent for `signature impersonation` → run **01-2 JWT Token (exchange)** to mint a token.\n\n**Notes**\n- Access tokens are short-lived; refresh tokens typically ~30 days.\n- Moving to Prod: switch ``{{authServer}}`` and re-consent; API base paths differ between demo/prod.", + "type": "text/plain" + }, "item": [ { - "id": "988f4f32-03c8-4f28-8466-c65ef0b94331", - "name": "Retrieve a list of agreements", + "id": "8591f95a-df37-444b-af68-9a23086fe588", + "name": "01 - JWT / Service Integration", + "description": { + "content": "Use JWT when your backend needs to call APIs without the user present. First, the target user (or an admin) must grant consent to your Integration Key for `signature impersonation`. Then your server signs a JWT with your **private key** and exchanges it for an access token.\n\n**Variables**\n\n| Variable | Required | Notes | Default |\n| --- | --- | --- | --- |\n| ``{{integrationKey}}`` | ✅ | Integration Key (OAuth client) | — |\n| ``{{userId}}`` | ✅ | Target user (GUID) to impersonate | — |\n| ``{{privateKey}}`` | ✅ | PEM for RS256 signing | — |\n| ``{{authServer}}`` | ✅ | Audience derived from this host | `https://account-d.docusign.com` |\n| ``{{scope}}`` | Optional | Scopes for the token | `adm_store_unified_repo_read models_read document_uploader_read document_uploader_write` |\n| ``{{USE_CUSTOM_ASSERTION}}`` | Optional | `true` to use your own ``{{jwt_assertion}}`` | `false` |", + "type": "text/plain" + }, + "item": [ + { + "id": "cdb5f283-1c9a-4fc5-bc63-32e45bfffe0b", + "name": "01-1 - Construct Consent URL (JWT)", + "request": { + "description": { + "content": "## **Grant Consent for JWT (Impersonation)**\n\n1. Execute this helper request.\n \n2. Open the returned authorizeUrl in a browser.\n \n3. Sign in and grant consent (must include `impersonation`).\n \n4. After consent is granted, you can close the browser.\n \n5. Run **01-1 - JWT Token (exchange)**.\n \n\n## **Get the Authorization Code**\n\n1. Execute the GET request of 02-1 - Construct Authorization URL.\n \n2. Open the returned authorizeUrl and open in a browser tab.\n \n3. Sign in, allow access and grant consent.\n \n4. The browser will redirect to your redirectUri.\n \n5. Copy the code value from the resulting URL query string.\n \n6. Paste the copied code into a new or existing Environment or Collection Variable named `{{authCodeNoPkce}}`.", + "type": "text/plain" + }, + "url": { + "port": "blank", + "host": [ + "about" + ], + "query": [], + "variable": [] + }, + "method": "GET" + }, + "response": [], + "event": [ + { + "listen": "prerequest", + "script": { + "id": "c36ef563-afdc-4198-861c-1943013aa6e2", + "type": "text/javascript", + "packages": {}, + "exec": [ + "const u = utils;", + "try {", + " const authServer = u.getVar(pm, 'authServer', undefined, { required: true });", + " const integrationKey = u.getVar(pm, 'integrationKey', undefined, { required: true });", + " const redirect = u.encVar(pm, 'redirectUri', undefined, { required: true });", + " let scopeStr = u.getScope(pm);", + " if (!String(scopeStr).split(/\\s+/).includes('impersonation')) scopeStr = (scopeStr + ' impersonation').trim();", + " const scopeParam = encodeURIComponent(scopeStr);", + " const authorize = `${authServer}/oauth/auth?response_type=code&client_id=${integrationKey}&redirect_uri=${redirect}&scope=${scopeParam}`;", + " const prompt = 'Open the URL, sign in, grant consent (JWT / impersonation). When done, you can close the browser and run 01-2 - JWT Token (exchange).';", + " pm.collectionVariables.set('_jwtHelper_authorizationUrl', authorize);", + " pm.collectionVariables.set('_jwtHelper_prompt', prompt);", + " // echo visual only", + " let echoUrl = 'https://postman-echo.com/response-headers'", + " + '?message=' + encodeURIComponent(u.asciiSafe(prompt))", + " + '&authorizeUrl=' + encodeURIComponent(authorize);", + " pm.request.method = 'GET';", + " pm.request.url = echoUrl;", + "} catch (e) {", + " pm.execution.setNextRequest(null);", + " throw e;", + "}" + ] + } + }, + { + "listen": "test", + "script": { + "id": "ed24f3a7-c6e3-4830-8f0d-9bcd26d851ee", + "type": "text/javascript", + "packages": {}, + "exec": [ + "try {", + " const url = pm.collectionVariables.get('_jwtHelper_authorizationUrl');", + " const txt = pm.collectionVariables.get('_jwtHelper_prompt');", + " let html = ``;", + " html += `
${txt}
${url}`;",
+ " pm.visualizer.set(html);",
+ "} catch(e){ pm.visualizer.set(`Helper error: ${e.message}
`); }" + ] + } + } + ] + }, + { + "id": "6d3f7e18-a6b6-4245-9e32-ccb0cbea8158", + "name": "01-2 - JWT Token (exchange)", + "request": { + "description": { + "content": "Exchanges the signed JWT (``{{jwt_assertion}}``) for an access token.\n\n**Two ways to supply the JWT assertion**\n1) **Auto-mint (default):** Set ``{{integrationKey}}``, ``{{userId}}``, ``{{authServer}}``, and ``{{privateKey}}``. The script mints a JWT and sets ``{{jwt_assertion}}`` for you.\n2) **Custom assertion:** Set ``{{USE_CUSTOM_ASSERTION}}`` to `true` **and** provide ``{{jwt_assertion}}`` yourself (PEM not needed).\n\n**Output:** ``{{access_token}}``. (JWT does **not** return a refresh token.)", + "type": "text/plain" + }, + "url": { + "path": [ + "oauth", + "token" + ], + "host": [ + "{{authServer}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/x-www-form-urlencoded" + } + ], + "method": "POST", + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "grant_type", + "value": "urn:ietf:params:oauth:grant-type:jwt-bearer" + }, + { + "key": "assertion", + "value": "{{jwt_assertion}}" + } + ] + }, + "auth": { + "type": "noauth", + "noauth": [] + } + }, + "response": [], + "event": [ + { + "listen": "prerequest", + "script": { + "id": "625de3e7-1eb7-454a-a566-c8d89fbaef4c", + "type": "text/javascript", + "exec": [ + "pm.environment.unset('jwt_error');", + "const USE_CUSTOM_ASSERTION = String(pm.environment.get('USE_CUSTOM_ASSERTION') || 'false').toLowerCase() === 'true';", + "try {", + " if (USE_CUSTOM_ASSERTION) {", + " // Require the caller to provide a ready-made JWT assertion", + " const custom = utils.getVar(pm, 'jwt_assertion', undefined, { required: true });", + " pm.environment.set('jwt_assertion', custom);", + " } else {", + " // Mint a new JWT assertion from key material", + " const integrationKey = utils.getVar(pm, 'integrationKey', undefined, { required: true });", + " const userId = utils.getVar(pm, 'userId', undefined, { required: true });", + " const authServer = utils.getVar(pm, 'authServer', undefined, { required: true });", + " const pem = utils.getVar(pm, 'privateKey', undefined, { required: true });", + " const scope = utils.getScope(pm);", + " const jwt = utils.mintJwt({ integrationKey, userId, authServer, privateKeyPem: pem, scope, expSeconds: 3600 });", + " pm.environment.set('jwt_assertion', jwt);", + " }", + "} catch(e){", + " pm.environment.set('jwt_error', e.message||String(e));", + " pm.execution.setNextRequest(null);", + " throw e;", + "}" + ] + } + }, + { + "listen": "test", + "script": { + "id": "0ccaca7f-210f-4445-a0e2-7329f19d65fa", + "type": "text/javascript", + "exec": [ + "const err = pm.environment.get('jwt_error');", + "if (err){ pm.test('❌ '+err, ()=>pm.expect.fail(err)); pm.environment.unset('jwt_error'); return; }", + "if (pm.response.code !== 200){", + " let why='Unknown error';", + " try{ const j=pm.response.json(); why=j.error||j.error_description||why; }catch(_){ }", + " pm.test(`❌ Token request failed (${pm.response.code})`, ()=>pm.expect.fail(why));", + " return;", + "}", + "const token = utils.storeTokensFromResponse(pm, pm.response.json());", + "pm.environment.unset('jwt_assertion');", + "pm.test('✅ Access token stored', ()=> pm.expect(token).to.be.a('string'));" + ] + } + } + ] + } + ], + "event": [] + }, + { + "id": "d7bd80e3-2a60-4fa3-a67a-da0e9f11aea1", + "name": " 02 - Authorization Code Grant (Confidential Client)", + "description": { + "content": "This folder implements the **Authorization Code Grant** flow. This process requires the user to be present initially to grant authorization through a browser-based login and consent screen.\n\nUpon successful consent, the system receives an authorization code which is exchanged for both a short-lived access token and a long-lived refresh token.\n\nThe key benefit of this approach is the ability to use the refresh token to continually request new access tokens in the background, thereby maintaining long-lived user sessions and enabling your server to execute automated tasks without repeated user interaction.\n\n**Variables**\n\nAuthorization Code Grant is a type of OAuth 2.0 flow used to obtain an access token. [Confidential Authorization Code Grant](https://developers.docusign.com/platform/auth/authcode/#confidential-authorization-code-grant), which should be used by apps that can secure a secret key.\n\n| Variable | Required | Notes | Default |\n| --- | --- | --- | --- |\n| ``{{integrationKey}}`` | ✅ | An integration key identifies your integration and links to its configuration values. [Create an integration key](https://developers.docusign.com/platform/configure-app/#how-to-get-an-integration-key). | |\n| ``{{clientSecret}}`` | ✅ | The secret key identifies your integration app through a unique key. [Create a Secret Key](https://developers.docusign.com/platform/configure-app/#secret-key). | |\n| ``{{redirectUri}}`` | ✅ | The URI is registered on your Docusign Integration Key (API Key). You can choose your application’s redirect uri. | |\n| ``{{authServer}}`` | ✅ | Authentication base URL (use [https://account.docusign.com](https://account.docusign.com) for Production). | `https://account-d.docusign.com` |\n| ``{{scope}}`` | Optional | Permissions requested (e.g., signature, impersonation for JWT).To see the full list of all supported scopes, see [Authentication scopes](https://developers.docusign.com/platform/auth/reference/scopes/). | ``adm_store_unified_repo_read models_read document_uploader_read document_uploader_write`` |\n| ``{{authCodeNoPkce}}`` | ✅ (Only on exchange) | Paste the `?code` here (env or collection var) | |", + "type": "text/plain" + }, + "item": [ + { + "id": "e5378c83-607a-4d7c-b802-197024ab5426", + "name": "02-1 - Construct Authorization URL", + "request": { + "description": { + "content": "## **Get the Authorization Code**\n\n1. Execute the GET request of 02-1 - Construct Authorization URL.\n \n2. Open the returned authorizeUrl and open in a browser tab.\n \n3. Sign in, allow access and grant consent.\n \n4. The browser will redirect to your redirectUri.\n \n5. Copy the code value from the resulting URL query string.\n \n6. Paste the copied code into a new or existing Environment or Collection Variable named ``{{authCodeNoPkce}}``.", + "type": "text/plain" + }, + "url": { + "port": "blank", + "host": [ + "about" + ], + "query": [], + "variable": [] + }, + "method": "GET" + }, + "response": [], + "event": [ + { + "listen": "prerequest", + "script": { + "id": "d620d88d-4f49-40ff-ae97-e7be69570ad3", + "type": "text/javascript", + "exec": [ + "const u = utils;", + "try {", + " const authServer = u.getVar(pm, 'authServer', undefined, { required: true });", + " const integrationKey = u.getVar(pm, 'integrationKey', undefined, { required: true });", + " const redirect = u.encVar(pm, 'redirectUri', undefined, { required: true });", + " const scopeStr = u.getScope(pm);", + " const scopeParam = encodeURIComponent(scopeStr);", + " const authorize = `${authServer}/oauth/auth?response_type=code&client_id=${integrationKey}&redirect_uri=${redirect}&scope=${scopeParam}`;", + " const prompt = 'Open the URL, sign in, grant consent, copy ?code= and paste it into an **environment or collection variable** named \"authCodeNoPkce\". Then run 02-2 - Exchange Authorization Code for Tokens.';", + " pm.collectionVariables.set('_confidentialHelper_authorizationUrl', authorize);", + " pm.collectionVariables.set('_confidentialHelper_prompt', prompt);", + " // echo visual only", + " let echoUrl = 'https://postman-echo.com/response-headers'", + " + '?message=' + encodeURIComponent(u.asciiSafe(prompt))", + " + '&authorizeUrl=' + encodeURIComponent(authorize);", + " pm.request.method = 'GET';", + " pm.request.url = echoUrl;", + "} catch (e) {", + " pm.execution.setNextRequest(null);", + " throw e;", + "}" + ] + } + }, + { + "listen": "test", + "script": { + "id": "fa031eb2-cdf5-4aac-8ce0-035c10afb605", + "type": "text/javascript", + "exec": [ + "try {", + " const url = pm.collectionVariables.get('_confidentialHelper_authorizationUrl');", + " const txt = pm.collectionVariables.get('_confidentialHelper_prompt');", + " let html = ``;", + " html += `${txt}
${url}`;",
+ " pm.visualizer.set(html);",
+ "} catch(e){ pm.visualizer.set(`Helper error: ${e.message}
`); }" + ] + } + } + ] + }, + { + "id": "6f393c10-2dfd-474b-9a41-61483672c5fc", + "name": "02-2 - Exchange Authorization Code for Tokens", + "request": { + "description": { + "content": "## **Exchanging Code for Tokens**\n\nThis request exchanges the temporary Authorization Code for usable access and refresh tokens.\n\n1. Verify that your environment or collection variables for ``{{integrationKey}}``, ``{{clientSecret}}``, and ``{{authCodeNoPkce}}`` are all populated with the correct values.\n \n2. Execute this request.\n \n3. Check the response body: The response will contain the `access_token` and `refresh_token`.\n \n4. The Pre-request or test script automatically extracts the access_token and refresh_token and saves them as environment variables. This lets you use the Bearer Token authentication instead of manual UI logins for later API calls.", + "type": "text/plain" + }, + "url": { + "path": [ + "oauth", + "token" + ], + "host": [ + "{{authServer}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/x-www-form-urlencoded" + } + ], + "method": "POST", + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "grant_type", + "value": "authorization_code" + }, + { + "key": "code", + "value": "{{authCodeNoPkce}}" + }, + { + "key": "client_id", + "value": "{{integrationKey}}" + }, + { + "key": "client_secret", + "value": "{{clientSecret}}" + } + ] + }, + "auth": { + "type": "noauth", + "noauth": [] + } + }, + "response": [], + "event": [ + { + "listen": "prerequest", + "script": { + "id": "e78e0825-c114-4a13-8e78-88fce1742e39", + "type": "text/javascript", + "exec": [ + "try {", + " // Accept either variables OR literal body params for these inputs:", + " utils.requireVarOrUrlencoded(pm, 'integrationKey', 'client_id', 'Integration Key (client_id)');", + " utils.requireVarOrUrlencoded(pm, 'clientSecret', 'client_secret', 'client secret (clientSecret/client_secret)');", + " utils.requireVarOrUrlencoded(pm, 'authCodeNoPkce', 'code', 'authorization code (authCodeNoPkce/code)');", + "} catch(e){ pm.execution.setNextRequest(null); throw e; }" + ] + } + }, + { + "listen": "test", + "script": { + "id": "4f58716f-5342-42d3-83b4-bf7490298d2e", + "type": "text/javascript", + "exec": [ + "pm.test('Access token returned', () => { pm.expect(pm.response.code).to.equal(200); pm.expect(pm.response.json()).to.have.property('access_token'); });", + "const token = utils.storeTokensFromResponse(pm, pm.response.json());", + "pm.test('✅ Access token stored', ()=> pm.expect(token).to.be.a('string'));" + ] + } + } + ] + } + ], + "event": [] + }, + { + "id": "8edafbee-dec8-4d9c-931c-1fea515a97b4", + "name": "03 - Authorization Code Grant with PKCE (Public Client)", + "description": { + "content": "This folder implements the **Public Authorization Code Grant (with PKCE)** flow, which is the required OAuth 2.0 standard for public applications like Single Page Applications (SPAs) and mobile apps.\n\nThis process requires the user to be present initially to grant authorization through a browser-based login and consent screen.\n\nUpon successful consent, the system receives an authorization code which is exchanged for both a short-lived access token and a long-lived refresh token.\n\nThe key benefit of this approach is the ability to use the refresh token to continually request new access tokens in the background, thereby maintaining long-lived user sessions and enabling your server to execute automated tasks without repeated user interaction.\n\n**Variables**\n\nPublic Authorization Code Grant (with PKCE) is a type of OAuth 2.0 flow used to obtain an access token. [Public Authorization Code Grant](https://developers.docusign.com/platform/auth/authcode/#public-authorization-code-grant), which does not require that your app secure a secret key.\n\n| Variable | Required | Notes | Default |\n| --- | --- | --- | --- |\n| ``{{publicIntegrationKey}}`` | ✅ | An integration key identifies your integration and links to its configuration values. [Create an integration key](https://developers.docusign.com/platform/configure-app/#how-to-get-an-integration-key). If absent, it falls back to ``{{integrationKey}}``. | |\n| ``{{integrationKey}}`` | Fallback | An integration key identifies your integration and links to its configuration values. [Create an integration key](https://developers.docusign.com/platform/configure-app/#how-to-get-an-integration-key). | |\n| ``{{redirectUri}}`` | ✅ | The URI is registered on your Docusign Integration Key (API Key). You can choose your application’s redirect uri. | |\n| ``{{authServer}}`` | ✅ | Authentication base URL (use [https://account.docusign.com](https://account.docusign.com) for Production). | `https://account-d.docusign.com` |\n| ``{{scope}}`` | Optional | Permissions requested (e.g., signature, impersonation for JWT).To see the full list of all supported scopes, see [Authentication scopes](https://developers.docusign.com/platform/auth/reference/scopes/). | ``adm_store_unified_repo_read models_read document_uploader_read document_uploader_write`` |", + "type": "text/plain" + }, + "item": [ + { + "id": "3b10a8c4-8160-4231-80b5-6274b15e948b", + "name": "03-1 - Construct Authorization URL with PKCE", + "request": { + "description": { + "content": "This request generates the authorization URL required to start the OAuth 2.0 flow.\n\n## Get the Authorization Code\n\n1. Execute the GET request of _03-1 - Construct Authorization URL_.\n \n2. Open the returned _authorizeUrl_ and open in a browser tab.\n \n3. Sign in, allow access and grant consent.\n \n4. The browser will redirect to your redirectUri.\n \n5. Copy the _code_ value from the resulting URL query string.\n \n\nPaste the copied _code_ into a new or existing Environment or Collection Variable named ``{{authCodePkce}}``.", + "type": "text/plain" + }, + "url": { + "port": "blank", + "host": [ + "about" + ], + "query": [], + "variable": [] + }, + "method": "GET", + "auth": { + "type": "noauth", + "noauth": [] + } + }, + "response": [], + "event": [ + { + "listen": "prerequest", + "script": { + "id": "248cffd2-13c0-42bb-b252-54dfad32c661", + "type": "text/javascript", + "exec": [ + "const u = utils;", + "try {", + " const authServer = u.getVar(pm, 'authServer', undefined, { required: true });", + " const redirect = u.encVar(pm, 'redirectUri', undefined, { required: true });", + " const scopeStr = u.getScope(pm);", + " // prefer explicit publicIntegrationKey; otherwise require integrationKey", + " const pubId = pm.environment.get('publicIntegrationKey') && pm.environment.get('publicIntegrationKey').trim();", + " const integrationKey = pubId ? pubId : u.getVar(pm, 'integrationKey', undefined, { required: true });", + " const { codeVerifier, codeChallenge } = u.ensurePkce(pm);", + " pm.environment.set('codeVerifier', codeVerifier);", + " pm.environment.set('codeChallenge', codeChallenge);", + " const url = `${authServer}/oauth/auth?response_type=code&client_id=${integrationKey}&redirect_uri=${redirect}&code_challenge_method=S256&code_challenge=${codeChallenge}&scope=${encodeURIComponent(scopeStr)}`;", + " const prompt = 'Open the URL, sign in, grant consent, copy ?code= and paste it into an **environment or collection variable** named \"authCodePkce\". Then run 03-2 - Exchange Authorization Code for Tokens (PKCE).';", + " pm.collectionVariables.set('_publicHelper_authorizationUrl', url);", + " pm.collectionVariables.set('_publicHelper_prompt', prompt);", + " let echoUrl = 'https://postman-echo.com/response-headers'", + " + '?message=' + encodeURIComponent(u.asciiSafe(prompt))", + " + '&authorizeUrl=' + encodeURIComponent(url);", + " pm.request.method='GET'; pm.request.url=echoUrl;", + "} catch (e) { pm.execution.setNextRequest(null); throw e; }" + ] + } + }, + { + "listen": "test", + "script": { + "id": "e09a4bf0-9392-4516-9238-5ce76937e6d4", + "type": "text/javascript", + "exec": [ + "try {", + " const url = pm.collectionVariables.get('_publicHelper_authorizationUrl');", + " const txt = pm.collectionVariables.get('_publicHelper_prompt');", + " let html = ``;", + " html += `${txt}
${url}`;",
+ " pm.visualizer.set(html);",
+ "} catch(e){ pm.visualizer.set(`Helper error: ${e.message}
`); }" + ] + } + } + ] + }, + { + "id": "9ad7641c-7681-4771-a550-58e63811f7c3", + "name": "03-2 - Exchange Authorization Code for Tokens (PKCE)", + "request": { + "description": { + "content": "## Exchanging Code for Tokens\n\nThis request exchanges the temporary Authorization Code using PKCE for usable access and refresh tokens.\n\n1. Verify that your environment or collection variables for ``{{integrationKey}}``, and ``{{authCodeWithPkce}}`` and the automatically generated ``{{code_verifier}}`` are all populated with the correct values.\n \n2. Ensure the Origin parameter added in Apps and Keys page is set in headers of _03-2 - Exchange Authorization Code for Tokens (PKCE)_ and CORS is activated with all the HTTP operations. For further information, refer [Set the CORS configuration of your app.](https://developers.docusign.com/platform/configure-app/#cors-configuration)\n \n3. Execute this request.\n \n4. Check the response body: The response will contain the _access_token_ and _refresh_token_.\n \n5. The Pre-request or test script should automatically extract and set the ``{{access_token}}`` and ``{{refresh_token}}`` variables for use in subsequent API calls.", + "type": "text/plain" + }, + "url": { + "path": [ + "oauth", + "token" + ], + "host": [ + "{{authServer}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/x-www-form-urlencoded" + } + ], + "method": "POST", + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "grant_type", + "value": "authorization_code" + }, + { + "key": "client_id", + "value": "{{publicIntegrationKey}}" + }, + { + "key": "code", + "value": "{{authCodePkce}}" + }, + { + "key": "code_verifier", + "value": "{{codeVerifier}}" + } + ] + }, + "auth": { + "type": "noauth", + "noauth": [] + } + }, + "response": [], + "event": [ + { + "listen": "prerequest", + "script": { + "id": "46c64040-3fe9-4ac8-948c-2456227ed1a5", + "type": "text/javascript", + "exec": [ + "try {", + " // Client ID can be body literal (client_id) OR a variable (publicIntegrationKey/integrationKey)", + " const hasLiteralClientId = utils.hasUrlencoded(pm, 'client_id');", + " const hasPublicVar = utils.isString(pm.environment.get('publicIntegrationKey')) || utils.isString(pm.collectionVariables.get('publicIntegrationKey')) || utils.isString(pm.globals.get('publicIntegrationKey'));", + " const hasClientVar = utils.isString(pm.environment.get('integrationKey')) || utils.isString(pm.collectionVariables.get('integrationKey')) || utils.isString(pm.globals.get('integrationKey'));", + " if (!hasLiteralClientId && !(hasPublicVar || hasClientVar)){", + " throw new Error('Missing client id. Set publicIntegrationKey/integrationKey or place a literal client_id in the body.');", + " }", + " utils.requireVarOrUrlencoded(pm, 'authCodePkce', 'code', 'authorization code (authCodePkce/code)');", + " utils.requireVarOrUrlencoded(pm, 'codeVerifier', 'code_verifier', 'PKCE code verifier (codeVerifier/code_verifier)');", + "} catch(e){ pm.execution.setNextRequest(null); throw e; }" + ] + } + }, + { + "listen": "test", + "script": { + "id": "7e7b5e18-78c2-4553-ac4c-7f6974641068", + "type": "text/javascript", + "exec": [ + "pm.test('Access token returned', () => { pm.expect(pm.response.code).to.equal(200); pm.expect(pm.response.json()).to.have.property('access_token'); });", + "const token = utils.storeTokensFromResponse(pm, pm.response.json());", + "pm.test('✅ Access token stored', ()=> pm.expect(token).to.be.a('string'));" + ] + } + } + ] + } + ], + "event": [] + }, + { + "id": "a750a827-a214-47aa-b382-ba96db74b5a7", + "name": "04 - Refresh Access Token", "request": { - "name": "Retrieve a list of agreements", "description": { - "content": "This operation retrieves a list of all agreements available in the system. It provides a high-level overview of each agreement, including its unique identifier (`id`), title, type, status, and involved parties. The list also includes important metadata, such as the agreement's creation and modification timestamps, and information on the agreement's source system (e.g., eSign, CLM).\n\nEach agreement entry includes essential details that allow users to quickly assess the agreements and determine which ones are relevant for their needs. For example, the agreement's status can help users understand whether an agreement is still active, pending, or completed.\n\nThe response also includes provisions that outline the key legal, financial, and lifecycle conditions, along with custom user-defined fields, providing a comprehensive understanding of each agreement.\n\n### Use Cases:\n- **Retrieving a list of agreements for integration into external systems**: Export or sync agreement data into other platforms (e.g., CRM, ERP systems) to align business processes across different tools.\n- **Providing data for RAG (Retrieval-Augmented Generation) applications or Copilots**: The list of agreements can be a valuable data source for AI/LLM-based applications that answer user queries about agreements. \n It allows Copilots to understand what agreements exist and offer insights based on their details.\n- **Filtering agreements by type or status**: Determine which agreements are active, pending, or completed, and gather a summary of key provisions across multiple agreements.\n- **Auditing or reporting**: Generate a report on agreements based on type, status, or date created, helping with compliance tracking and internal reviews.\n- **Metadata tracking**: Track when agreements were created, modified, and by whom, ensuring proper governance and version control.\n\n### Key Features:\n- **Comprehensive Agreement Overview**: Provides high-level visibility into all agreements, with essential details for each one, including status, type, and involved parties.\n- **Metadata and Provisions**: Returns important metadata and provisions (legal, financial, and custom) for each agreement, helping users understand their obligations and contract terms.\n- **Source System Information**: Captures details about where the agreement originated (e.g., eSign, CLM), making it easier to integrate and track agreements across different business systems.\n- **Data for AI Applications**: The operation is designed to support LLM-powered apps, making it ideal for use in RAG-based applications and Copilots that query agreements for decision-making or information purposes.\n", + "content": "This request uses the long-lived refresh token to obtain a new access token, ensuring continuous API access without user re-authentication.\n\n1. Verify that the ``{{refresh_token}}`` variable is populated from the previous \"Exchange Code for Tokens\" request.\n \n2. Execute this request.\n \n3. The response will contain a brand new _access_token_.\n \n4. The test script should automatically extract and overwrite the old value of the ``{{access_token}}`` variable with the new token.", "type": "text/plain" }, "url": { "path": [ - "agreements" + "oauth", + "token" + ], + "host": [ + "{{authServer}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/x-www-form-urlencoded" + } + ], + "method": "POST", + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "grant_type", + "value": "refresh_token" + }, + { + "key": "client_id", + "value": "{{integrationKey}}" + }, + { + "key": "refresh_token", + "value": "{{refresh_token}}" + } + ] + }, + "auth": { + "type": "basic", + "basic": [ + { + "type": "string", + "value": "{{clientSecret}}", + "key": "password" + }, + { + "type": "string", + "value": "{{integrationKey}}", + "key": "username" + } + ] + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "id": "7c6940ce-cfb4-478c-88d2-43864740d99e", + "type": "text/javascript", + "exec": [ + "pm.test('Token refreshed', () => { pm.expect(pm.response.code).to.equal(200); pm.expect(pm.response.json()).to.have.property('access_token'); });", + "", + "if (pm.response.code === 200) {", + " var TOKEN = UTILS.STORETOKENSFROMRESPONSE(PM, PM.RESPONSE.JSON());", + " PM.TEST('✅ ACCESS TOKEN STORED', ()=> PM.EXPECT(TOKEN).TO.BE.A('STRING'));", + "}" + ] + } + } + ] + }, + { + "id": "b1d8b6d2-db85-4892-8d81-ef06ecb48615", + "name": "05 - User Info", + "request": { + "description": { + "content": "The **User Info** request serves as the validation step following any successful OAuth 2.0 flow. It confirms the access token's validity and retrieves the fundamental identity details of your Docusign account.\n\n- **Identity Validation:** The primary response fields, such as `\"sub\"` (the user ID), `\"name\"`, and `\"email\"`, confirms **who** the application is acting on behalf of.\n \n- **API Configuration:.** The default account contains the `account_id` (`1b63b53e-xxxx-4728-xxxx-e5aef8f305d1`) and the correct `base_uri`. Your application must extract these values to construct the correct endpoints for making calls like sending envelopes or managing templates.\n \n\nThis request validates the entire authentication process and supplies all the required user and account context to interact with the Docusign API.", + "type": "text/plain" + }, + "url": { + "path": [ + "oauth", + "userinfo" + ], + "host": [ + "{{authServer}}" + ], + "query": [], + "variable": [] + }, + "method": "GET" + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "id": "e5243341-3831-47af-b222-ef657be7fb8f", + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test('UserInfo returned', () => { pm.expect(pm.response.code).to.equal(200); });", + "let j = {};", + "try { j = pm.response.json(); } catch(_) {}", + "if (j && Array.isArray(j.accounts) && j.accounts.length){", + " const def = j.accounts.find(a => a.is_default) || j.accounts[0];", + " if (def && def.account_id) pm.environment.set('account_id', def.account_id);", + " if (def && def.base_uri) pm.environment.set('base_uri', def.base_uri);", + "}", + "pm.test('✅ Parsed userinfo (optional vars stored if present)', () => pm.expect(true).to.equal(true));" + ] + } + } + ] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "id": "3b1dc9b7-e4ab-43dd-9267-ba72d9c5d73f", + "type": "text/javascript", + "packages": { + "npm:jsrsasign@11.1.0": { + "id": "npm:jsrsasign@11.1.0" + } + }, + "exec": [ + "/* ------------------------------------------------------------------", + " * utils: Shared helpers for the Auth folder (folder-level pre-request).", + " * These run before each request in this folder. Pass `pm` into helpers.", + " * ------------------------------------------------------------------ */", + "utils = (function(){", + " const jsrsasign = pm.require('npm:jsrsasign@11.1.0');", + " const { KJUR, KEYUTIL } = jsrsasign;", + "", + " /** isString(v): true if v is a non-empty string */", + " const isString = v => typeof v === 'string' && v.trim() !== '';", + "", + " /** isPlaceholder(v): true if value looks like a {{variable}} */", + " const isPlaceholder = v => isString(v) && v.startsWith('{{') && v.endsWith('}}');", + "", + " /** asciiSafe(s): strip non-ASCII for header-safe echo endpoints */", + " const asciiSafe = s => String(s||'').replace(/[^\\x20-\\x7E]/g, '');", + "", + " function _missingMsg(name){", + " return `Missing ${name}. Set it in your active Environment or in Collection variables.`;", + " }", + "", + " /**", + " * getVar(pm, name, fallback, {required=false})", + " * Resolve var from env → collection → globals. Throws if required and missing.", + " * @returns {string}", + " */", + " function getVar(pm_, name, fallback, { required = false } = {}){", + " const sources = [pm_.environment.get(name), pm_.collectionVariables.get(name), pm_.globals.get(name)];", + " const v = sources.find(isString);", + " if (v !== undefined) return v;", + " if (required) { throw new Error(_missingMsg(name)); }", + " return (fallback !== undefined ? fallback : `{{${name}}}`);", + " }", + "", + " /** encVar(pm, name, fallback, opt): getVar + encodeURIComponent (unless placeholder) */", + " function encVar(pm_, name, fallback, opt){", + " const v = getVar(pm_, name, fallback, opt);", + " return isPlaceholder(v) ? v : encodeURIComponent(v);", + " }", + "", + " /** getScope(pm): returns scope string (defaults to 'adm_store_unified_repo_read models_read document_uploader_read document_uploader_write') */", + " function getScope(pm_){", + " return getVar(pm_, 'scope', 'adm_store_unified_repo_read models_read document_uploader_read document_uploader_write');", + " }", + "", + " /** deriveBaseHost(url): strips scheme or uses URL.host */", + " function deriveBaseHost(u){", + " try { return new URL(u).host; }", + " catch { return String(u||'').replace(/^(https?:\\/\\/)/i,''); }", + " }", + "", + " /**", + " * Safely add/remove a urlencoded body param by key using body.update().", + " */", + " function setUrlencodedEnabled(pm_, key, enabled){", + " const body = pm_.request && pm_.request.body;", + " if (!body || body.mode !== 'urlencoded') return;", + " let current = [];", + " try {", + " if (body.urlencoded && typeof body.urlencoded.toJSON === 'function') {", + " current = body.urlencoded.toJSON();", + " } else if (body.urlencoded && typeof body.urlencoded.all === 'function') {", + " current = body.urlencoded.all();", + " } else if (Array.isArray(body.urlencoded)) {", + " current = body.urlencoded;", + " }", + " } catch(_) {}", + " const filtered = current.filter(p => p.key !== key);", + " const next = enabled ? filtered.concat({ key, value: '', type: 'text' }) : filtered;", + " body.update({ mode: 'urlencoded', urlencoded: next });", + " }", + "", + " // ---- presence checks in urlencoded vs vars --------------------------------", + " function _urlencodedList(pm_){", + " const body = pm_.request && pm_.request.body;", + " if (!body || body.mode !== 'urlencoded') return [];", + " try {", + " if (body.urlencoded && typeof body.urlencoded.toJSON === 'function') return body.urlencoded.toJSON();", + " if (Array.isArray(body.urlencoded)) return body.urlencoded;", + " } catch(_) {}", + " return [];", + " }", + " function hasUrlencoded(pm_, key){", + " const row = _urlencodedList(pm_).find(p => p.key === key);", + " if (!row) return false;", + " const val = (row.value||'').trim();", + " return val !== '' && !isPlaceholder(val);", + " }", + " function requireVarOrUrlencoded(pm_, varName, bodyKey, displayName){", + " const hasVar = isString(pm_.environment.get(varName)) || isString(pm_.collectionVariables.get(varName)) || isString(pm_.globals.get(varName));", + " if (hasVar || hasUrlencoded(pm_, bodyKey)) return;", + " throw new Error(_missingMsg(displayName || varName));", + " }", + "", + " // ---- PKCE helpers -------------------------------------------------------", + " const toB64Url = s => s.replace(/\\+/g,'-').replace(/\\//g,'_').replace(/=+$/, '');", + " const hexToBytes = h => (h.match(/.{2}/g)||[]).map(x=>parseInt(x,16));", + "", + " /** sha256b64url(s): SHA-256 of string → base64url */", + " function sha256b64url(s){", + " const hex = KJUR.crypto.Util.sha256(s);", + " const raw = String.fromCharCode(...hexToBytes(hex));", + " return toB64Url(btoa(raw));", + " }", + "", + " /**", + " * ensurePkce(pm): returns { codeVerifier, codeChallenge }, generating if missing.", + " */", + " function ensurePkce(pm_){", + " let codeVerifier = pm_.environment.get('codeVerifier');", + " if (!codeVerifier){", + " const bytes = new Uint8Array(32); crypto.getRandomValues(bytes);", + " const v1 = toB64Url(btoa(String.fromCharCode(...bytes)));", + " bytes.reverse();", + " const v2 = toB64Url(btoa(String.fromCharCode(...bytes)));", + " codeVerifier = (v1+v2).slice(0,96);", + " pm_.environment.set('codeVerifier', codeVerifier);", + " }", + " let codeChallenge = pm_.environment.get('codeChallenge');", + " if (!codeChallenge){ codeChallenge = sha256b64url(codeVerifier); pm_.environment.set('codeChallenge', codeChallenge); }", + " return { codeVerifier, codeChallenge };", + " }", + "", + " // ---- JWT mint -----------------------------------------------------------", + " /**", + " * mintJwt({ integrationKey, userId, authServer, privateKeyPem, scope, expSeconds=3600 })", + " * Signs an RS256 JWT for Docusign OAuth (aud = authServer host).", + " * @returns {string} Signed JWT", + " */", + " function mintJwt({ integrationKey, userId, authServer, privateKeyPem, scope, expSeconds = 3600 }){", + " const aud = deriveBaseHost(authServer);", + " const now = Math.floor(Date.now()/1000);", + " const head = { typ: 'JWT', alg: 'RS256' };", + " const body = { iss: integrationKey, sub: userId, aud, iat: now, exp: now + expSeconds, scope: scope || 'adm_store_unified_repo_read models_read document_uploader_read document_uploader_write' };", + " const keyObj = KEYUTIL.getKey(privateKeyPem);", + " return KJUR.jws.JWS.sign('RS256', JSON.stringify(head), JSON.stringify(body), keyObj);", + " }", + "", + " // ---- Token storage (env → collection → runtime; snake_case only) -------", + " function _setScopedOne(pm_, key, val){", + " if (val == null) return false;", + " try { pm_.environment.set(key, val); return true; } catch(_) {}", + " try { pm_.collectionVariables.set(key, val); return true; } catch(_) {}", + " try { pm_.variables.set(key, val); return true; } catch(_) {}", + " return false;", + " }", + " function _unsetAll(pm_, key){", + " try { pm_.environment.unset(key); } catch(_) {}", + " try { pm_.collectionVariables.unset(key); } catch(_) {}", + " try { pm_.variables.unset(key); } catch(_) {}", + " }", + "", + " /**", + " * storeTokensFromResponse(pm, r): saves tokens to env/collection/runtime in snake_case.", + " * Sets: access_token, refresh_token, token_type, expires_in, access_token_expires_at, received_at.", + " * @returns {string|null} access_token", + " */", + " function storeTokensFromResponse(pm_, r){", + " if (!r){", + " ['access_token','refresh_token','token_type','expires_in','access_token_expires_at','received_at'].forEach(k=>_unsetAll(pm_,k));", + " return null;", + " }", + " if (r.access_token != null) _setScopedOne(pm_, 'access_token', r.access_token); else _unsetAll(pm_, 'access_token');", + " if (r.refresh_token != null) _setScopedOne(pm_, 'refresh_token', r.refresh_token); else _unsetAll(pm_, 'refresh_token');", + " if (r.token_type != null) _setScopedOne(pm_, 'token_type', r.token_type); else _unsetAll(pm_, 'token_type');", + " if (r.expires_in != null){", + " _setScopedOne(pm_, 'expires_in', r.expires_in);", + " const expAt = String(Math.floor(Date.now()/1000) + Number(r.expires_in||0));", + " _setScopedOne(pm_, 'access_token_expires_at', expAt);", + " } else {", + " _unsetAll(pm_, 'expires_in');", + " _unsetAll(pm_, 'access_token_expires_at');", + " }", + " if (r.access_token) _setScopedOne(pm_, 'received_at', new Date().toISOString()); else _unsetAll(pm_, 'received_at');", + " return r.access_token || null;", + " }", + "", + " return {", + " isString, isPlaceholder, asciiSafe, deriveBaseHost, mintJwt,", + " getVar: (pm_, n, f, o)=>getVar(pm_, n, f, o), encVar: (pm_, n, f, o)=>encVar(pm_, n, f, o), getScope: (pm_)=>getScope(pm_),", + " setUrlencodedEnabled: (pm_, k, e)=>setUrlencodedEnabled(pm_, k, e), ensurePkce: (pm_)=>ensurePkce(pm_),", + " hasUrlencoded: (pm_, k)=>hasUrlencoded(pm_, k), requireVarOrUrlencoded: (pm_, vn, bk, dn)=>requireVarOrUrlencoded(pm_, vn, bk, dn),", + " storeTokensFromResponse: (pm_, r)=>storeTokensFromResponse(pm_, r)", + " };", + "})();" + ] + } + } + ] + }, + { + "id": "c7e093e1-1ee3-4d7b-841f-e2af2bf505fd", + "name": "BulkJob", + "description": { + "content": "", + "type": "text/plain" + }, + "item": [ + { + "id": "97a51ce5-3dbd-4d24-8603-af23bbf1e104", + "name": "Create new bulk job with presigned URLs direct to Azure Blob Store", + "request": { + "name": "Create new bulk job with presigned URLs direct to Azure Blob Store", + "description": { + "content": "Create a new job, give pre-signed URLs back, the client will upload to Azure Blob Store directly.\n\n[Required scopes](/docs/navigator-api/auth/): `document_uploader_write`, `document_uploader_read`\n\n**Important Upload Workflow**:\n1. Call this endpoint to create a job and receive upload URLs\n2. For each document in the response's `_embedded.documents` array, extract the `upload_document` URL from `_actions`\n3. Upload your document file to each URL using an HTTP PUT request with the document content as binary data\n4. After all documents are uploaded, call the `/actions/complete` endpoint to finalize the job\n5. Use the GET endpoint to monitor job progress\n\n**Example response structure**:\n```json\n{\n \"_embedded\": {\n \"documents\": [\n {\n \"id\": \"8c566d26-e7fb-4b7e-870c-1d0fb8df9084\",\n \"sequence\": 1,\n \"_actions\": {\n \"upload_document\": \"https://docupstoragewestwu3dsto.blob.core.windows.net/...\"\n }\n }\n ]\n }\n}\n```\n\n**Azure Blob Storage Upload Instructions**:\n\nUse the pre-signed URL from step 2 to upload your document directly to Azure Blob Storage:\n\n```\nPUT [pre-signed URL from _actions.upload_document]\n\nHeaders:\n- x-ms-blob-type: BlockBlob\n- x-ms-meta-filename: YourDocumentName.pdf\n- Content-Type: application/pdf\n\nBody: [Your document binary data]\n```\n\n**Important Notes**:\n- The `upload_document` URLs are pre-signed Azure Blob Storage URLs with time-limited validity (8 hours)\n- The `x-ms-meta-filename` header should contain your original document filename\n- The `x-ms-blob-type` must be set to `BlockBlob`\n- Setting the `Content-Type` header is recommended to match your document type\n- If `Content-Type` is not specified, Azure defaults to `application/octet-stream`\n\n**Firewall & Network Configuration**:\n\nIf your organization uses firewalls or network restrictions, you may need to whitelist the following Azure Blob Storage domains \nto ensure successful document uploads. The upload URLs returned by this API will use one of these domains based on your \naccount's geographic region:\n\n**Primary Storage Endpoints**:\n- `https://docupstorageaustauepsto.blob.core.windows.net/`\n- `https://docupstoragecanacacpsto.blob.core.windows.net/`\n- `https://docupstoragecentcuspsto.blob.core.windows.net/`\n- `https://docupstorageeasteu2psto.blob.core.windows.net/`\n- `https://docupstorageeasteusdsto.blob.core.windows.net/` (Demo)\n- `https://docupstoragejapajpepsto.blob.core.windows.net/`\n- `https://docupstoragenortneupsto.blob.core.windows.net/`\n- `https://docupstoragewestweupsto.blob.core.windows.net/`\n- `https://docupstoragewestwu3dsto.blob.core.windows.net/` (Demo)\n\n**Secondary Storage Endpoints** (for redundancy/failover):\n- `https://docupstorageaustauepsto-secondary.blob.core.windows.net/`\n- `https://docupstoragecanacacpsto-secondary.blob.core.windows.net/`\n- `https://docupstoragecentcuspsto-secondary.blob.core.windows.net/`\n- `https://docupstorageeasteu2psto-secondary.blob.core.windows.net/`\n- `https://docupstorageeasteusdsto-secondary.blob.core.windows.net/` (Demo)\n- `https://docupstoragejapajpepsto-secondary.blob.core.windows.net/`\n- `https://docupstoragenortneupsto-secondary.blob.core.windows.net/`\n- `https://docupstoragewestweupsto-secondary.blob.core.windows.net/`\n- `https://docupstoragewestwu3dsto-secondary.blob.core.windows.net/` (Demo)\n\n**Note**: You may whitelist all domains listed above, or contact your DocuSign administrator to determine which specific \nregion(s) your account uses to minimize the whitelist scope.\n\n**Supported File Formats & Content Types**:\n\nThe table below shows common file formats and their recommended Content-Type headers. \n**Note**: For the most up-to-date list of supported formats, headers, and constraints, always refer to the \n`_action_templates` object in the API response, which provides dynamic configuration including:\n- `allowed_formats`: Current list of supported file extensions\n- `headers`: Required HTTP headers with examples\n- `constraints`: Maximum file size and other limits\n- `success_status_code`: Expected response code for successful uploads\n\n| Format | Extension | Content-Type |\n|--------|-----------|--------------|\n| PDF | .pdf | `application/pdf` |\n| Word Document (2007+) | .docx | `application/vnd.openxmlformats-officedocument.wordprocessingml.document` |\n| Word Document (Legacy) | .doc | `application/msword` |\n| PowerPoint Presentation (2007+) | .pptx | `application/vnd.openxmlformats-officedocument.presentationml.presentation` |\n| PowerPoint Presentation (Legacy) | .ppt | `application/vnd.ms-powerpoint` |\n| PowerPoint Slideshow | .ppsx | `application/vnd.openxmlformats-officedocument.presentationml.slideshow` |\n| Excel Workbook (2007+) | .xlsx | `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` |\n| Excel Workbook (Legacy) | .xls | `application/vnd.ms-excel` |\n| Excel Binary Workbook | .xlsb | `application/vnd.ms-excel.sheet.binary.macroenabled.12` |\n| Rich Text Format | .rtf | `text/rtf` |\n| WordPerfect Document | .wpd | `application/vnd.wordperfect` |\n| HTML | .html, .htm | `text/html` |\n| JPEG Image | .jpg, .jpeg | `image/jpeg` |\n| PNG Image | .png | `image/png` |\n| TIFF Image | .tif, .tiff | `image/tiff` |\n\n**Example Upload Requests**:\n\nPDF Document:\n```\nPUT https://storage.blob.core.windows.net/container/doc-id?signature=...\nContent-Type: application/pdf\nx-ms-blob-type: BlockBlob\nx-ms-meta-filename: contract.pdf\n\n[Binary PDF data]\n```\n\nWord Document:\n```\nPUT https://storage.blob.core.windows.net/container/doc-id?signature=...\nContent-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document\nx-ms-blob-type: BlockBlob\nx-ms-meta-filename: agreement.docx\n\n[Binary DOCX data]\n```\n\nImage:\n```\nPUT https://storage.blob.core.windows.net/container/doc-id?signature=...\nContent-Type: image/jpeg\nx-ms-blob-type: BlockBlob\nx-ms-meta-filename: signed-page.jpg\n\n[Binary JPEG data]\n```\n", + "type": "text/plain" + }, + "url": { + "path": [ + "v1", + "accounts", + ":accountId", + "upload", + "jobs" ], "host": [ "{{baseUrl}}" ], - "query": [ + "query": [], + "variable": [ { - "disabled": true, + "disabled": false, "description": { - "content": "The maximum number of items that can be returned in a single page.", + "content": "(Required) ", + "type": "text/plain" + }, + "type": "any", + "value": "00000000-0000-0000-0000-000000000000", + "key": "accountId" + } + ] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "application/json" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"expected_number_of_docs\": \"