diff --git a/assets/maestro-collection.json b/assets/maestro-collection.json
index 4395d18..ea908f8 100644
--- a/assets/maestro-collection.json
+++ b/assets/maestro-collection.json
@@ -1,61 +1,2583 @@
{
+ "_": {
+ "postman_id": "04a29038-2c87-45e0-950a-62797505f573"
+ },
"item": [
{
- "name": "WorkflowTrigger",
- "description": "",
- "item": []
+ "id": "237addb1-ceed-4f4a-8113-9ab6872d6675",
+ "name": "🔐 Quick Auth Setup → Then Run APIs",
+ "description": {
+ "content": "This folder contains a curated set of requests for rapid Docusign integration. By configuring authentication at the folder level, you can execute all contained requests without manual per request setup. Successful execution of the authentication flows within this folder will populate the **Environment and Collection variables** ``{{access_token}}`` and ``{{refresh_token}}``.\n\nOnce these values are saved to your active environment, they will be globally available for all requests in this folder.\n\nEvery request in this folder is configured with auth type as **inherit auth from the parent**. To ensure seamless execution, the folder itself is set to the **Bearer Token** authorization type, using ``{{access_token}}`` as the value.\n\n**Note**: When viewing the Folder's **Authorization** tab, ensure the **Token** field contains only the variable ``{{access_token}}``. Do not include the word \"Bearer\" in the text box, as Postman automatically generates the correct ``Authorization: Bearer [token]`` header.\n\n## **Choose your Authentication Type**\n\nDocusign uses OAuth 2.0 to secure your API requests. Using OAuth, your app requests access and performs actions, such as requesting a signature, on behalf of one of your users.\n\nDocusign provides four scenarios for implementing OAuth:\n\n- [Authenticate with the JWT Grant](https://developers.docusign.com/platform/auth/jwt-get-token/)\n- [Authenticate with the Confidential Authorization Code Grant](https://developers.docusign.com/platform/auth/confidential-authcode-get-token/)\n- [Authenticate with Public Authorization Code Grant](https://developers.docusign.com/platform/auth/public-authcode-get-token/)\n- [Authenticate with Implicit Code Grant](https://developers.docusign.com/platform/auth/implicit/)\n\n| Flow | When to use | Human present? | Client secret? |\n|------|-------------|---------------|----------------|\n| **JWT (Service Integration)** | Server/daemon jobs acting on behalf of a user after one-time consent has been granted. | No (after consent) | No (requires privateKey) |\n| **Confidential Authorization Code Grant** | Server-side applications that can securely store a secret. Supports refresh_token. | Yes (initial sign-in) | Yes |\n| **Public Authorization Code Grant (PKCE)** | SPA, Mobile, or Desktop apps that cannot securely store a secret. | Yes (initial sign-in) | No (uses PKCE flow) |\n\n## Prerequisites\n\nBefore obtaining the access token, ensure the following environment or collection variables are configured in Postman.\n\n| Variable | Example Value | Description |\n|----------|---------------|-------------|\n| ``{{authServer}}`` | Demo: https://account-d.docusign.com
Production: https://account.docusign.com | Authentication base URL. |\n| ``{{redirectUri}}`` | http://localhost:8080/ | A redirect URI (callback URI) where Docusign sends users after authentication. |\n| ``{{scope}}`` | signature extended | Permissions requested (e.g., signature, impersonation for JWT). See: https://developers.docusign.com/platform/auth/reference/scopes/ |\n| ``{{integrationKey}}`` | Example: f8db556a-xxxx-4f30-xxxx-648ea46axxxx | Integration key identifying your app. Create one: https://developers.docusign.com/platform/configure-app/#how-to-get-an-integration-key |\n| ``{{clientSecret}}`` | Example: f2db256a-xxxx-4f30-xxxx-64a2346axxxx | Secret key for confidential integrations: https://developers.docusign.com/platform/configure-app/#secret-key |\n| ``{{publicIntegrationKey}}`` | Example: f2db256a-xxxx-4f30-xxxx-64a2346axxxx | Public integration key used for PKCE flows. |\n| ``{{userId}}`` | Example: f2db256a-xxxx-4f30-xxxx-64a2346axxxx | User GUID. Find it here: https://developers.docusign.com/platform/configure-app/#user-id |\n| ``{{privateKey}}`` | -----BEGIN RSA PRIVATE KEY----- ... -----END RSA PRIVATE KEY----- | RSA private key for JWT flow: https://developers.docusign.com/platform/configure-app/#rsa-key-pair |\n\n## Steps to get token\n\n1. JWT (Service Integration)\n \n 1. Open the **01 - JWT / Service Integration** folder.\n \n 2. Execute the GET request of **01-1 – Construct Consent URL**.\n \n 3. Open the returned **authorizeUrl** in a browser.\n \n 4. Sign in and grant consent (must include **impersonation**).\n \n 5. After consent is granted, you can close the browser.\n \n 6. Run **01-2 - JWT Token (exchange)**\n \n2. Confidential Auth Code\n \n 1. Open the **02 – Authorization Code Grant (Confidential Client)** folder.\n \n 2. Execute the GET request of **02-1 – Construct Authorization URL**.\n \n 3. Open the returned **authorizeUrl** in a browser tab.\n \n 4. Sign in and grant consent.\n \n 5. Copy the **?code=** value from the URL and set it as ``{{authCodeNoPkce}}``.\n \n 6. Run **02-2 – Exchange Authorization Code for Tokens**.\n \n3. Public Auth Code (PKCE)\n \n 1. Open the **03 – Authorization Code Grant with PKCE (Public Client)** folder**.**\n \n 2. Execute the GET request of **03-1 – Construct Authorization URL with PKCE**.\n \n 3. Open the returned **authorizeUrl** in a browser tab.\n \n 4. Sign in and grant consent.\n \n 5. Copy the **?code=** value from the URL and set it as ``{{authCodePkce}}``.\n \n 6. 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 \n 7. Run **03-2 – Exchange Authorization Code for Tokens (PKCE)**.\n \n4. Execute 05 – User Info to verify your user details and base URI.\n \n\n## Notes\n\n- If the access token has expired, execute 04 – Refresh Access Token using the refresh token. Default expiration is 8 hours (`expires_in` is in seconds).\n \n- Moving to Production: Switch ``{{authServer}}`` to [https://account.docusign.com](https://account.docusign.com) and re-consent. The base URI can be accessed by executing 05 – User Info.",
+ "type": "text/plain"
+ },
+ "item": [
+ {
+ "id": "3586d893-4131-46c1-b32b-306d0ce0fd39",
+ "name": "01 - JWT / Service Integration",
+ "description": {
+ "content": "This request demonstrates authentication using JSON Web Tokens (JWT) Grant for accessing APIs without user interaction.\n\n1. Before making the first call, an administrator or the target user must grant consent to your **Integration Key** (Client ID) to allow specific scopes.To see the full list of all supported scopes, see [Authentication scopes](https://developers.docusign.com/platform/auth/reference/scopes/).\n \n2. Your server constructs and digitally signs a **JWT** using your **private key** and the user's ID.\n \n3. The signed JWT is exchanged with the authorization server for a short-lived access token. This access token is then used in subsequent API calls.\n \n\nThis workflow is ideal for background processes, scheduled tasks, and integrations that require impersonating a user without constant user interaction.\n\n**Variables**\n\nFor context around what JWT Grant authentication is, when you should use it, and its advantages and disadvantages, see [JSON Web Token (JWT) Grant](https://developers.docusign.com/platform/auth/jwt/).\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| ``{{userId}}`` | ✅ | Find your [User ID](https://developers.docusign.com/platform/configure-app/#user-id) in the Apps and Keys page. | — |\n| ``{{privateKey}}`` | ✅ | The **PEM formatted Private Key** used for RS256 signing the JWT. | — |\n| ``{{authServer}}`` | ✅ | Authentication base URL (use 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/). | ``aow_manage`` |\n| ``{{USE_CUSTOM_ASSERTION}}`` | Optional | `true` to use your own ``{{jwt_assertion}}`` | `false` |",
+ "type": "text/plain"
+ },
+ "item": [
+ {
+ "id": "b5c53852-fb57-42b3-ba5c-0434506ef395",
+ "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-2 - JWT Token (exchange)**.",
+ "type": "text/plain"
+ },
+ "url": {
+ "port": "blank",
+ "host": [
+ "about"
+ ],
+ "query": [],
+ "variable": []
+ },
+ "method": "GET"
+ },
+ "response": [],
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "id": "7c639d0e-702e-41e7-ba6c-f9549fb7c494",
+ "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": "7df89e1f-a9c3-43cc-9375-07144165f5d5",
+ "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": "372ebea7-1876-4c2b-9b45-233c4dca7043", + "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": "29f81ee4-3e1a-478f-bd8d-3afe6ec904d4", + "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": "7de531ca-dbb4-4721-a54c-a3229cfa3164", + "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": "06dcc0bf-a4c0-4c09-87aa-e4c3cd2d4228", + "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/). | ``aow_manage`` |\n| ``{{authCodeNoPkce}}`` | ✅ (Only on exchange) | Paste the `?code` here (env or collection var) | |", + "type": "text/plain" + }, + "item": [ + { + "id": "76f21c53-5724-43ee-b3fa-dc70836ec0e8", + "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": "d8a01f84-d6a2-4c56-aaf1-69bec0c2b2ee", + "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": "14868876-e8c9-4cf2-8157-9848d691f523", + "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": "8e2e5ead-6bab-40ca-ac1b-c03ffb5ae01b", + "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": "c74f37be-7009-4d52-9d46-980d6abbe95a", + "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": "19866320-f6db-4414-b3f2-ea1bd39e3fbb", + "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": "f41d8170-f2a0-46cd-9794-b3735e8a2761", + "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/). | ``aow_manage`` |", + "type": "text/plain" + }, + "item": [ + { + "id": "64e613e6-77cd-4886-8ade-feacdda3d5de", + "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 with PKCE_.\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": "e371d31b-1c6a-4eae-be9b-d5a81f3b716b", + "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": "299dd66e-c250-4dd0-9d55-47e53d601437", + "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": "abf30d8c-31d2-42f2-9992-04e6a9fd2372", + "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" + }, + { + "key": "Origin", + "value": "https://localhost:3000" + } + ], + "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": "4a8c1139-c818-4d63-8d88-6f2516e9aca1", + "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": "633a7af3-43c6-43cb-80af-af3225ba84cd", + "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": "679ff7c3-f1fa-4ba1-b447-9d9649849bc6", + "name": "04 - Refresh Access Token", + "request": { + "description": { + "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": [ + "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": "02fb7d64-367c-4e4f-ab1c-5b41c081a3c9", + "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": "ea77f67c-0279-4ed6-b82d-02f58426dce1", + "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": "a80d63f7-a9d3-4677-bc27-2adf8ebe934e", + "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": "7c0f3533-607a-44d7-a94b-068ab0cee926", + "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 'aow_manage') */", + " function getScope(pm_){", + " return getVar(pm_, 'scope', 'aow_manage');", + " }", + "", + " /** 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 || 'aow_manage' };", + " 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": "a1254999-b5dd-4ac4-ae91-0fce3fbb9835", "name": "WorkflowInstanceManagement", - "description": "", - "item": [] - }, - { - "name": "WorkflowManagement", - "description": "", - "item": [] - }, - { - "name": "Workflows", - "description": "", + "description": { + "content": "", + "type": "text/plain" + }, "item": [ { - "id": "709655ee-9af3-4e02-8f09-45f04b08dfb3", - "name": "Retrieve a list of available Maestro workflows", + "id": "c213eda0-56a5-4cdd-a385-e6e07017b873", + "name": "Retrieve All Workflow Instances", + "request": { + "name": "Retrieve All Workflow Instances", + "description": { + "content": "This operation retrieves a list of all available Maestro workflow instances. It returns basic information\nabout each workflow instance, including its unique identifier (`id`), name, status, timestamps, and\nadditional metadata.\n\nThe response provides key details that help users understand what workflow instances are in progress\nor completed, and the relevant data for each. Each workflow instance entry also includes metadata, such\nas who started it, when it was last modified, and how many steps have been completed.\n\n### Use Cases:\n- Listing all available workflow instances for manual or automated review\n- Monitoring which workflow instances are currently running or have finished\n- Gathering basic metadata about workflow instances for auditing, logging, or reporting purposes\n\n### Key Features:\n- **Comprehensive Instance Overview**: Provides a full list of workflow instances, giving visibility\n into all ongoing and completed workflows within the Maestro platform\n- **Metadata for Tracking**: Includes helpful metadata like creation time, last modification date,\n and user details to support audit trails\n- **Scalable and Future-Proof**: Designed to handle growing numbers of workflow instances as the\n platform scales\n", + "type": "text/plain" + }, + "url": { + "path": [ + "v1", + "accounts", + ":accountId", + "workflows", + ":workflowId", + "instances" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) The unique identifier of the account.", + "type": "text/plain" + }, + "type": "any", + "value": "00000000-0000-0000-0000-000000000000", + "key": "accountId" + }, + { + "disabled": false, + "description": { + "content": "(Required) ", + "type": "text/plain" + }, + "type": "any", + "value": "00000000-0000-0000-0000-000000000000", + "key": "workflowId" + } + ] + }, + "header": [ + { + "key": "Accept", + "value": "application/json" + } + ], + "method": "GET", + "body": {} + }, + "response": [ + { + "id": "235057e0-87a0-4891-a568-2ff011a3f53b", + "name": "Successful response containing a list of workflow instances", + "originalRequest": { + "url": { + "path": [ + "v1", + "accounts", + ":accountId", + "workflows", + ":workflowId", + "instances" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Accept", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: oauth2", + "type": "text/plain" + }, + "key": "Authorization", + "value": "