{
  "item": [
    {
      "id": "51413a06-84db-4446-a49b-a6408bf68062",
      "name": "Authentication",
      "description": {
        "content": "",
        "type": "text/plain"
      },
      "item": [
        {
          "id": "2b62bfee-e8a6-483c-bc50-0875517c1937",
          "name": "Onboard a new user and organization",
          "request": {
            "name": "Onboard a new user and organization",
            "description": {
              "content": "Create a new Juno user and organization linked to your partner integration. Optional taxSoftware and practiceManagementSoftware values are documented on the request schema.",
              "type": "text/plain"
            },
            "url": {
              "path": [
                "partner-api",
                "auth",
                "onboard"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [],
              "variable": []
            },
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "POST",
            "auth": null,
            "body": {
              "mode": "raw",
              "raw": "{\n  \"email\": \"<string>\",\n  \"password\": \"<string>\",\n  \"firstName\": \"<string>\",\n  \"lastName\": \"<string>\",\n  \"organizationName\": \"<string>\",\n  \"organizationSize\": \"<string>\",\n  \"externalUserId\": \"<string>\",\n  \"externalOrgId\": \"<string>\",\n  \"partnerId\": \"<string>\",\n  \"emailConfirmed\": \"<boolean>\",\n  \"returns\": \"<number>\",\n  \"businessReturns\": \"<number>\",\n  \"taxSoftware\": \"<string>\",\n  \"practiceManagementSoftware\": \"<string>\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "id": "2dbd030a-3e7d-4f23-941a-2950c730e14f",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "auth",
                    "onboard"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"email\": \"user@example.com\",\n  \"password\": \"StrongPassword123!\",\n  \"firstName\": \"John\",\n  \"lastName\": \"Doe\",\n  \"organizationName\": \"TechCorp Inc.\",\n  \"organizationSize\": \"50-100\",\n  \"externalUserId\": \"user_abc123\",\n  \"externalOrgId\": \"org_abc123\",\n  \"partnerId\": \"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11\",\n  \"emailConfirmed\": false,\n  \"returns\": 10,\n  \"businessReturns\": 100,\n  \"taxSoftware\": \"LACERTE\",\n  \"practiceManagementSoftware\": \"TAXDOME\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Created",
              "code": 201,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"id\": \"c3d4e5f6-a7b8-9012-cdef-123456789012\",\n  \"email\": \"jane@example.com\",\n  \"role\": \"USER\",\n  \"firstName\": {},\n  \"lastName\": {},\n  \"orgId\": {}\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "7468c050-8a2d-4ac1-bae5-2026e7d88c9c",
              "name": "Request validation failed",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "auth",
                    "onboard"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"email\": \"user@example.com\",\n  \"password\": \"StrongPassword123!\",\n  \"firstName\": \"John\",\n  \"lastName\": \"Doe\",\n  \"organizationName\": \"TechCorp Inc.\",\n  \"organizationSize\": \"50-100\",\n  \"externalUserId\": \"user_abc123\",\n  \"externalOrgId\": \"org_abc123\",\n  \"partnerId\": \"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11\",\n  \"emailConfirmed\": false,\n  \"returns\": 10,\n  \"businessReturns\": 100,\n  \"taxSoftware\": \"LACERTE\",\n  \"practiceManagementSoftware\": \"TAXDOME\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 400,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/auth/onboard\",\n  \"method\": \"POST\",\n  \"message\": [\n    \"externalUserId should not be empty\"\n  ]\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "e4ec3c5d-1628-4f9d-ad71-282330b2fe8c",
              "name": "Partner organization already exists, or user is already linked to a partner",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "auth",
                    "onboard"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"email\": \"user@example.com\",\n  \"password\": \"StrongPassword123!\",\n  \"firstName\": \"John\",\n  \"lastName\": \"Doe\",\n  \"organizationName\": \"TechCorp Inc.\",\n  \"organizationSize\": \"50-100\",\n  \"externalUserId\": \"user_abc123\",\n  \"externalOrgId\": \"org_abc123\",\n  \"partnerId\": \"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11\",\n  \"emailConfirmed\": false,\n  \"returns\": 10,\n  \"businessReturns\": 100,\n  \"taxSoftware\": \"LACERTE\",\n  \"practiceManagementSoftware\": \"TAXDOME\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 409,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/auth/onboard\",\n  \"method\": \"POST\",\n  \"message\": \"Partner organization already exists\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "9d9a5312-02c0-49c3-bad5-f3b8a5e51b54",
              "name": "Error onboarding partner user",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "auth",
                    "onboard"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"email\": \"user@example.com\",\n  \"password\": \"StrongPassword123!\",\n  \"firstName\": \"John\",\n  \"lastName\": \"Doe\",\n  \"organizationName\": \"TechCorp Inc.\",\n  \"organizationSize\": \"50-100\",\n  \"externalUserId\": \"user_abc123\",\n  \"externalOrgId\": \"org_abc123\",\n  \"partnerId\": \"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11\",\n  \"emailConfirmed\": false,\n  \"returns\": 10,\n  \"businessReturns\": 100,\n  \"taxSoftware\": \"LACERTE\",\n  \"practiceManagementSoftware\": \"TAXDOME\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Internal Server Error",
              "code": 500,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 500,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/auth/onboard\",\n  \"method\": \"POST\",\n  \"message\": \"Error onboarding partner user\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            }
          ],
          "event": [],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        },
        {
          "id": "7b3b5e07-99c3-41f6-bc5e-f5be4bdbddcf",
          "name": "Onboard an existing TruePrep user to a partner org",
          "request": {
            "name": "Onboard an existing TruePrep user to a partner org",
            "description": {
              "content": "Link an existing Juno user (userId) to your partner organization. Use when the user already has a Juno account.",
              "type": "text/plain"
            },
            "url": {
              "path": [
                "partner-api",
                "auth",
                "onboard",
                "current-user"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [],
              "variable": []
            },
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "POST",
            "auth": null,
            "body": {
              "mode": "raw",
              "raw": "{\n  \"externalUserId\": \"<string>\",\n  \"externalOrgId\": \"<string>\",\n  \"partnerId\": \"<string>\",\n  \"orgId\": \"<string>\",\n  \"userId\": \"<string>\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "id": "324343c7-5b88-4d68-91fc-6d759bbc7e5a",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "auth",
                    "onboard",
                    "current-user"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"externalUserId\": \"user_abc123\",\n  \"externalOrgId\": \"org_abc123\",\n  \"partnerId\": \"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11\",\n  \"orgId\": \"b2c3d4e5-f6a7-8901-bcde-f12345678901\",\n  \"userId\": \"c3d4e5f6-a7b8-9012-cdef-123456789012\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Created",
              "code": 201,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"status\": 200,\n  \"partnerUser\": {\n    \"id\": \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\",\n    \"userId\": \"c3d4e5f6-a7b8-9012-cdef-123456789012\",\n    \"partnerId\": \"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11\",\n    \"externalId\": \"user_abc123\",\n    \"createdAt\": \"2026-06-08T12:00:00.000Z\",\n    \"isActive\": true\n  },\n  \"partnerOrg\": {\n    \"id\": \"b2c3d4e5-f6a7-8901-bcde-f12345678901\",\n    \"organizationId\": \"b2c3d4e5-f6a7-8901-bcde-f12345678901\",\n    \"partnerId\": \"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11\",\n    \"externalId\": \"org_abc123\",\n    \"createdAt\": \"2026-06-08T12:00:00.000Z\",\n    \"isActive\": true\n  }\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "400fe690-578b-4c23-99f3-7e90e7c0604d",
              "name": "External organization and user IDs are required, user not found, or validation failed",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "auth",
                    "onboard",
                    "current-user"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"externalUserId\": \"user_abc123\",\n  \"externalOrgId\": \"org_abc123\",\n  \"partnerId\": \"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11\",\n  \"orgId\": \"b2c3d4e5-f6a7-8901-bcde-f12345678901\",\n  \"userId\": \"c3d4e5f6-a7b8-9012-cdef-123456789012\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 400,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/auth/onboard/current-user\",\n  \"method\": \"POST\",\n  \"message\": \"External organization and user IDs are required\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "ea9740f3-8957-48ca-9c49-69c97cd9bb6d",
              "name": "Error onboarding user to partner",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "auth",
                    "onboard",
                    "current-user"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"externalUserId\": \"user_abc123\",\n  \"externalOrgId\": \"org_abc123\",\n  \"partnerId\": \"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11\",\n  \"orgId\": \"b2c3d4e5-f6a7-8901-bcde-f12345678901\",\n  \"userId\": \"c3d4e5f6-a7b8-9012-cdef-123456789012\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Internal Server Error",
              "code": 500,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 500,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/auth/onboard/current-user\",\n  \"method\": \"POST\",\n  \"message\": \"Error onboarding user to partner\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            }
          ],
          "event": [],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        },
        {
          "id": "6eec5374-5a69-46ac-a272-a5b16113d510",
          "name": "Pre-onboard a user and get an onboarding link",
          "request": {
            "name": "Pre-onboard a user and get an onboarding link",
            "description": {
              "content": "Step 1 of partner onboarding (partner backend POST). Returns a `redirectUrl` for the user's browser (step 2 GET). After onboarding, Juno redirects the browser to your `callbackUrl` with tokens (step 3 GET). Requires X-Partner-Api-Key.\n\nTwo hosts are involved:\n- api.juno.tax — partner backend calls (POST/GET with API key + Bearer token)\n- app.juno.tax — user browser redirects during onboarding (GET only)\n\nRecommended onboarding flow:\n| Step | Method | Caller | Endpoint | Purpose |\n| 1 | POST | Partner backend | api.juno.tax/partner-api/auth/pre-onboard | Validate callback URL, get onboarding link |\n| 2 | GET | User browser | app.juno.tax/onboarding/partner?... | User signs up / logs in on Juno |\n| 3 | GET | User browser | <your callbackUrl>?accessToken&refreshToken | Deliver tokens to partner (current flow) |\n| 4 | GET | Partner backend | <your callbackUrl> handler | Extract tokens server-side |\n| 5 | POST | Partner backend | api.juno.tax/partner-api/... | API calls with Bearer + X-Partner-Api-Key |\n| 6 | POST | Partner backend | api.juno.tax/partner-api/auth/refresh | Renew tokens when access token expires |\n\nBrowser redirects use query parameters (withCallbackUrl, orgId, userId, partnerId). Partner API calls use JSON request bodies and Authorization headers — never put tokens in URLs for steps 5–6.\n\nPlanned change (future): step 3 will deliver a one-time authorization code via GET redirect; step 4 becomes POST /partner-api/auth/token (server-to-server code exchange), matching the OAuth authorization-code pattern already used by Juno Connect integrations.\n\nKnown limitation — token callback via query parameters:\nAfter onboarding, Juno redirects the user's browser to your callbackUrl with accessToken and refreshToken as URL query parameters. Tokens in URLs can be exposed via browser history, referrer headers, proxy logs, and server access logs.\n\nPlanned remediation (future):\nJuno will replace query-parameter token delivery with a short-lived, one-time authorization code that partners exchange server-to-server over HTTPS. Partners will no longer receive JWTs in callback URLs. Juno will provide a migration guide before the change ships.\n\nInterim mitigations (required until migration):\n- Register callback URLs on HTTPS origins only; Juno validates against your whitelisted callback origins\n- Handle the callback on your backend — never persist tokens in client-side storage from the redirect\n- Extract tokens immediately, then redirect the user to a clean URL with query parameters stripped\n- Never log callback URLs, query strings, or token values\n- Store tokens server-side only and use POST /partner-api/auth/refresh for renewal",
              "type": "text/plain"
            },
            "url": {
              "path": [
                "partner-api",
                "auth",
                "pre-onboard"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [],
              "variable": []
            },
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "POST",
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "x-partner-api-key"
                },
                {
                  "key": "value",
                  "value": "{{partnerApiKey}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"userId\": \"<string>\",\n  \"orgId\": \"<string>\",\n  \"callbackUrl\": \"<string>\",\n  \"firstName\": \"<string>\",\n  \"lastName\": \"<string>\",\n  \"email\": \"<string>\",\n  \"companyName\": \"<string>\",\n  \"practiceManagementSoftware\": \"<string>\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "id": "e2d58d53-09dd-4316-9e74-67194025dc3a",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "auth",
                    "pre-onboard"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: apikey",
                      "type": "text/plain"
                    },
                    "key": "x-partner-api-key",
                    "value": "<API Key>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"userId\": \"user_abc123\",\n  \"orgId\": \"org_abc123\",\n  \"callbackUrl\": \"https://yourapp.com/callback\",\n  \"firstName\": \"Jane\",\n  \"lastName\": \"Smith\",\n  \"email\": \"jane@example.com\",\n  \"companyName\": \"Acme Tax LLC\",\n  \"practiceManagementSoftware\": \"TAXDOME\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Created",
              "code": 201,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"redirectUrl\": \"https://app.juno.tax/onboarding/partner?orgId=org_abc123&userId=user_abc123&withCallbackUrl=https%3A%2F%2Fyourapp.com%2Fcallback&partnerId=a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "e5fcea8e-5ae9-4845-b4ad-42e70b868631",
              "name": "Unknown Callback URL, or request validation failed",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "auth",
                    "pre-onboard"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: apikey",
                      "type": "text/plain"
                    },
                    "key": "x-partner-api-key",
                    "value": "<API Key>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"userId\": \"user_abc123\",\n  \"orgId\": \"org_abc123\",\n  \"callbackUrl\": \"https://yourapp.com/callback\",\n  \"firstName\": \"Jane\",\n  \"lastName\": \"Smith\",\n  \"email\": \"jane@example.com\",\n  \"companyName\": \"Acme Tax LLC\",\n  \"practiceManagementSoftware\": \"TAXDOME\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 400,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/auth/pre-onboard\",\n  \"method\": \"POST\",\n  \"message\": [\n    \"callbackUrl should not be empty\"\n  ]\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "36b693fb-51b6-40fe-94ac-41668ef25c43",
              "name": "Missing API key or Invalid API key",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "auth",
                    "pre-onboard"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: apikey",
                      "type": "text/plain"
                    },
                    "key": "x-partner-api-key",
                    "value": "<API Key>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"userId\": \"user_abc123\",\n  \"orgId\": \"org_abc123\",\n  \"callbackUrl\": \"https://yourapp.com/callback\",\n  \"firstName\": \"Jane\",\n  \"lastName\": \"Smith\",\n  \"email\": \"jane@example.com\",\n  \"companyName\": \"Acme Tax LLC\",\n  \"practiceManagementSoftware\": \"TAXDOME\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Unauthorized",
              "code": 401,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 401,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/auth/pre-onboard\",\n  \"method\": \"POST\",\n  \"message\": \"Missing API key\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            }
          ],
          "event": [],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        },
        {
          "id": "5d78fad2-2643-49a0-8b43-237a3076bba6",
          "name": "Refresh a partner user access token",
          "request": {
            "name": "Refresh a partner user access token",
            "description": {
              "content": "Exchange a refresh token for a new access/refresh token pair. Tokens must be sent in the request body — never in URLs. Requires X-Partner-Api-Key.\n\nWhen the access token expires (~60 minutes), call POST /partner-api/auth/refresh before re-authenticating the user.\n\nRequest:\n- POST /partner-api/auth/refresh\n- Headers: X-Partner-Api-Key, Content-Type: application/json\n- Body: { \"refreshToken\": \"<stored refresh token>\" }\n\nSuccess (200):\n- Response: { \"accessToken\": \"...\", \"refreshToken\": \"...\" }\n- Both tokens are rotated — persist the new pair and discard the old refresh token\n- Retry the original API request once with the new accessToken\n\nRefresh failure (401):\n- Messages: \"Invalid refresh token\" or \"Token expired or invalid\"\n- The refresh token has expired (~30 days), been revoked, or does not match the active session\n- Clear stored tokens for that user and restart onboarding (POST /partner-api/auth/pre-onboard)\n\nImplementation notes:\n- On 401 from a partner API call, attempt refresh once, then retry the original request once\n- Do not loop refresh + retry indefinitely\n- Serialize refresh per user/session — concurrent refreshes invalidate earlier refresh tokens\n- Proactive refresh (e.g. before access token expiry) avoids mid-request failures",
              "type": "text/plain"
            },
            "url": {
              "path": [
                "partner-api",
                "auth",
                "refresh"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [],
              "variable": []
            },
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "POST",
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "x-partner-api-key"
                },
                {
                  "key": "value",
                  "value": "{{partnerApiKey}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"refreshToken\": \"{{refreshToken}}\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "id": "f4cccb5f-e618-4bbe-b048-f7bd0a476e6c",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "auth",
                    "refresh"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: apikey",
                      "type": "text/plain"
                    },
                    "key": "x-partner-api-key",
                    "value": "<API Key>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"refreshToken\": \"<string>\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"accessToken\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\n  \"refreshToken\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "78722786-c146-4865-9f8c-b9ba29cae51c",
              "name": "Missing/Invalid API key, Invalid refresh token, or Token expired or invalid",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "auth",
                    "refresh"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: apikey",
                      "type": "text/plain"
                    },
                    "key": "x-partner-api-key",
                    "value": "<API Key>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"refreshToken\": \"<string>\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Unauthorized",
              "code": 401,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 401,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/auth/refresh\",\n  \"method\": \"POST\",\n  \"message\": \"Missing API key\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            }
          ],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "if (pm.response.code === 200 || pm.response.code === 201) {",
                  "  const json = pm.response.json();",
                  "  if (json.accessToken) pm.collectionVariables.set('accessToken', json.accessToken);",
                  "  if (json.refreshToken) pm.collectionVariables.set('refreshToken', json.refreshToken);",
                  "}"
                ]
              }
            }
          ],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        },
        {
          "id": "4493176e-3ca2-4918-8047-55899c877404",
          "name": "Authenticate a partner user (internal admin use)",
          "request": {
            "name": "Authenticate a partner user (internal admin use)",
            "description": {
              "content": "Internal admin endpoint for linking partner users and issuing partner tokens. Requires administrator Bearer access token.",
              "type": "text/plain"
            },
            "url": {
              "path": [
                "partner-api",
                "auth",
                "authenticate"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [],
              "variable": []
            },
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "POST",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{bearerToken}}"
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"externalUserId\": \"<string>\",\n  \"externalOrgId\": \"<string>\",\n  \"partnerId\": \"<string>\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "id": "005336f3-4afc-4b56-aa84-675b8e32cafa",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "auth",
                    "authenticate"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: bearer",
                      "type": "text/plain"
                    },
                    "key": "Authorization",
                    "value": "Bearer <token>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"externalUserId\": \"user_abc123\",\n  \"externalOrgId\": \"org_abc123\",\n  \"partnerId\": \"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"accessToken\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\n  \"refreshToken\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\n  \"user\": {\n    \"id\": \"c3d4e5f6-a7b8-9012-cdef-123456789012\",\n    \"email\": \"jane@example.com\",\n    \"role\": \"USER\",\n    \"firstName\": {},\n    \"lastName\": {},\n    \"orgId\": {}\n  }\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "d8909d55-e27d-4677-91f9-d9ae5ea4731b",
              "name": "Request validation failed",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "auth",
                    "authenticate"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: bearer",
                      "type": "text/plain"
                    },
                    "key": "Authorization",
                    "value": "Bearer <token>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"externalUserId\": \"user_abc123\",\n  \"externalOrgId\": \"org_abc123\",\n  \"partnerId\": \"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 400,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/auth/authenticate\",\n  \"method\": \"POST\",\n  \"message\": [\n    \"externalUserId should not be empty\"\n  ]\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "92031228-948b-4749-9ccc-168caf793830",
              "name": "User not authenticated, invalid partner linkage, or insufficient role",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "auth",
                    "authenticate"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: bearer",
                      "type": "text/plain"
                    },
                    "key": "Authorization",
                    "value": "Bearer <token>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"externalUserId\": \"user_abc123\",\n  \"externalOrgId\": \"org_abc123\",\n  \"partnerId\": \"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Unauthorized",
              "code": 401,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 401,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/auth/authenticate\",\n  \"method\": \"POST\",\n  \"message\": \"User not authenticated\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            }
          ],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "if (pm.response.code === 200 || pm.response.code === 201) {",
                  "  const json = pm.response.json();",
                  "  if (json.accessToken) pm.collectionVariables.set('accessToken', json.accessToken);",
                  "  if (json.refreshToken) pm.collectionVariables.set('refreshToken', json.refreshToken);",
                  "}"
                ]
              }
            }
          ],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        }
      ],
      "event": []
    },
    {
      "id": "46ef0592-079c-4b94-bea1-334b5ccacf43",
      "name": "Documents",
      "description": {
        "content": "",
        "type": "text/plain"
      },
      "item": [
        {
          "id": "6aee3bf0-3018-4c1c-bf7e-0f1d21645496",
          "name": "1. Generate a pre-signed S3 URL for document upload",
          "request": {
            "name": "Generate a pre-signed S3 URL for document upload",
            "description": {
              "content": "Step 1 of document upload. Returns a presigned URL — PUT the file to signed_url, then pass url as s3Url in POST /documents/upload. documentId must match the ID used in the upload step. Requires X-Partner-Api-Key and Bearer access token.",
              "type": "text/plain"
            },
            "url": {
              "path": [
                "partner-api",
                "documents",
                "secure-link"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [],
              "variable": []
            },
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "POST",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{bearerToken}}"
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"documentId\": \"{{documentId}}\",\n  \"documentName\": \"<string>\",\n  \"mimeType\": \"<string>\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "id": "a513ad33-614e-44c4-8582-52f7b5295b84",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "documents",
                    "secure-link"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: bearer",
                      "type": "text/plain"
                    },
                    "key": "Authorization",
                    "value": "Bearer <token>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"documentId\": \"doc_abc123\",\n  \"documentName\": \"w2-2025.pdf\",\n  \"mimeType\": \"application/pdf\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Created",
              "code": 201,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"signed_url\": \"https://bucket.s3.amazonaws.com/env/uuid_w2-2025.pdf?X-Amz-...\",\n  \"url\": \"s3://bucket-name/env/uuid_w2-2025.pdf\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "af25d42f-aa72-4e9c-b4b3-391f4583ddb5",
              "name": "Request validation failed",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "documents",
                    "secure-link"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: bearer",
                      "type": "text/plain"
                    },
                    "key": "Authorization",
                    "value": "Bearer <token>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"documentId\": \"doc_abc123\",\n  \"documentName\": \"w2-2025.pdf\",\n  \"mimeType\": \"application/pdf\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 400,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/documents/secure-link\",\n  \"method\": \"POST\",\n  \"message\": [\n    \"documentName should not be empty\"\n  ]\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "b90f04e4-8188-41b8-8657-0b70f00415ae",
              "name": "Missing/Invalid API key or Unauthorized access token",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "documents",
                    "secure-link"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: bearer",
                      "type": "text/plain"
                    },
                    "key": "Authorization",
                    "value": "Bearer <token>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"documentId\": \"doc_abc123\",\n  \"documentName\": \"w2-2025.pdf\",\n  \"mimeType\": \"application/pdf\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Unauthorized",
              "code": 401,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 401,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/documents/secure-link\",\n  \"method\": \"POST\",\n  \"message\": \"Missing API key\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "97908f49-cfab-4d7a-9dc0-bea87b8c6b79",
              "name": "Unexpected failure (e.g. storage error). Uses the standard error envelope; message text varies.",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "documents",
                    "secure-link"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: bearer",
                      "type": "text/plain"
                    },
                    "key": "Authorization",
                    "value": "Bearer <token>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"documentId\": \"doc_abc123\",\n  \"documentName\": \"w2-2025.pdf\",\n  \"mimeType\": \"application/pdf\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Internal Server Error",
              "code": 500,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 401,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/account/returns-usage\",\n  \"method\": \"GET\",\n  \"message\": \"Unauthorized\",\n  \"stack\": \"string\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            }
          ],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "if (pm.response.code === 201) {",
                  "  const json = pm.response.json();",
                  "  if (json.signed_url) pm.collectionVariables.set('signedUrl', json.signed_url);",
                  "  if (json.url) pm.collectionVariables.set('s3Url', json.url);",
                  "}"
                ]
              }
            }
          ],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        },
        {
          "id": "44461acd-873e-43e3-84df-784289f46acc",
          "name": "2. Upload file to S3 (presigned URL)",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/pdf",
                "description": "MIME type of the file being uploaded"
              }
            ],
            "body": {
              "mode": "file",
              "file": {}
            },
            "url": "{{signedUrl}}",
            "description": "Step 2 of document upload (not part of the Juno API). PUT file bytes directly to the presigned URL from '1. Generate a pre-signed S3 URL'. On success, call '3. Register an uploaded document' with s3Url set to the url field from step 1."
          },
          "response": [],
          "event": []
        },
        {
          "id": "48e321d5-a5f2-459c-a2d7-c3a068fe4fa1",
          "name": "3. Register an uploaded document and trigger processing",
          "request": {
            "name": "Register an uploaded document and trigger processing",
            "description": {
              "content": "Step 2 of document upload. Registers the S3 object from secure-link and starts processing. Field requirements depend on preparationType — see request schema for documentType, taxYear, client vs business fields. Requires X-Partner-Api-Key and Bearer access token.",
              "type": "text/plain"
            },
            "url": {
              "path": [
                "partner-api",
                "documents",
                "upload"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [],
              "variable": []
            },
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "POST",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{bearerToken}}"
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"s3Url\": \"{{s3Url}}\",\n  \"clientId\": \"<string>\",\n  \"taxYear\": \"<number>\",\n  \"documentId\": \"{{documentId}}\",\n  \"documentType\": \"<string>\",\n  \"preparationType\": \"<string>\",\n  \"businessName\": \"<string>\",\n  \"taxIdentifier\": \"<string>\",\n  \"clientFirstName\": \"<string>\",\n  \"clientLastName\": \"<string>\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "id": "22b33893-08ea-42cd-8585-bfa96f5269b1",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "documents",
                    "upload"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: bearer",
                      "type": "text/plain"
                    },
                    "key": "Authorization",
                    "value": "Bearer <token>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"s3Url\": \"s3://bucket-name/env/uuid_w2-2025.pdf\",\n  \"clientId\": \"client_abc123\",\n  \"taxYear\": 2025,\n  \"documentId\": \"doc_abc123\",\n  \"documentType\": \"SOURCE\",\n  \"preparationType\": \"FORM_1040\",\n  \"businessName\": \"Acme Corp\",\n  \"taxIdentifier\": \"12-3456789\",\n  \"clientFirstName\": \"Jane\",\n  \"clientLastName\": \"Smith\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Created",
              "code": 201,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"id\": \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\",\n  \"externalDocumentId\": \"doc_abc123\",\n  \"taxDocumentId\": \"b2c3d4e5-f6a7-8901-bcde-f12345678901\",\n  \"status\": \"UPLOADED\",\n  \"createdAt\": \"2026-06-08T12:00:00.000Z\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "207ce368-543a-49a0-a21a-30889f903892",
              "name": "Validation failed, client ID conflict, or document limit reached (trial)",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "documents",
                    "upload"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: bearer",
                      "type": "text/plain"
                    },
                    "key": "Authorization",
                    "value": "Bearer <token>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"s3Url\": \"s3://bucket-name/env/uuid_w2-2025.pdf\",\n  \"clientId\": \"client_abc123\",\n  \"taxYear\": 2025,\n  \"documentId\": \"doc_abc123\",\n  \"documentType\": \"SOURCE\",\n  \"preparationType\": \"FORM_1040\",\n  \"businessName\": \"Acme Corp\",\n  \"taxIdentifier\": \"12-3456789\",\n  \"clientFirstName\": \"Jane\",\n  \"clientLastName\": \"Smith\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 400,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/documents/upload\",\n  \"method\": \"POST\",\n  \"message\": [\n    \"s3Url should not be empty\"\n  ]\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "a9c65d8e-2077-41da-9ca3-5214e6fae1ef",
              "name": "Missing/Invalid API key or Unauthorized access token",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "documents",
                    "upload"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: bearer",
                      "type": "text/plain"
                    },
                    "key": "Authorization",
                    "value": "Bearer <token>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"s3Url\": \"s3://bucket-name/env/uuid_w2-2025.pdf\",\n  \"clientId\": \"client_abc123\",\n  \"taxYear\": 2025,\n  \"documentId\": \"doc_abc123\",\n  \"documentType\": \"SOURCE\",\n  \"preparationType\": \"FORM_1040\",\n  \"businessName\": \"Acme Corp\",\n  \"taxIdentifier\": \"12-3456789\",\n  \"clientFirstName\": \"Jane\",\n  \"clientLastName\": \"Smith\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Unauthorized",
              "code": 401,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 401,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/documents/upload\",\n  \"method\": \"POST\",\n  \"message\": \"Missing API key\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "e152966a-7bc5-45d7-a7fd-505f3e7e980a",
              "name": "Subscription not found, purchase/trial limit reached, or document limit exceeded",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "documents",
                    "upload"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: bearer",
                      "type": "text/plain"
                    },
                    "key": "Authorization",
                    "value": "Bearer <token>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"s3Url\": \"s3://bucket-name/env/uuid_w2-2025.pdf\",\n  \"clientId\": \"client_abc123\",\n  \"taxYear\": 2025,\n  \"documentId\": \"doc_abc123\",\n  \"documentType\": \"SOURCE\",\n  \"preparationType\": \"FORM_1040\",\n  \"businessName\": \"Acme Corp\",\n  \"taxIdentifier\": \"12-3456789\",\n  \"clientFirstName\": \"Jane\",\n  \"clientLastName\": \"Smith\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Forbidden",
              "code": 403,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 403,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/documents/upload\",\n  \"method\": \"POST\",\n  \"message\": \"Valid subscription not found\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "e8dacb3f-91ca-46cf-afa8-ec2e43e8930c",
              "name": "Failed to create or find tax preparation, or internal server error",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "documents",
                    "upload"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: bearer",
                      "type": "text/plain"
                    },
                    "key": "Authorization",
                    "value": "Bearer <token>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"s3Url\": \"s3://bucket-name/env/uuid_w2-2025.pdf\",\n  \"clientId\": \"client_abc123\",\n  \"taxYear\": 2025,\n  \"documentId\": \"doc_abc123\",\n  \"documentType\": \"SOURCE\",\n  \"preparationType\": \"FORM_1040\",\n  \"businessName\": \"Acme Corp\",\n  \"taxIdentifier\": \"12-3456789\",\n  \"clientFirstName\": \"Jane\",\n  \"clientLastName\": \"Smith\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Internal Server Error",
              "code": 500,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 500,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/documents/upload\",\n  \"method\": \"POST\",\n  \"message\": \"Failed to create or find tax preparation after 5 retries\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            }
          ],
          "event": [],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        },
        {
          "id": "f728d9b7-37b3-4216-9473-f336ceef7941",
          "name": "4. Get processing status of a document",
          "request": {
            "name": "Get processing status of a document",
            "description": {
              "content": "Returns the current processing state for a document you previously registered via POST /partner-api/documents/upload.\n\nPath parameter `id` is your `documentId` from the upload request (not Juno's internal ID). See the 200 response schema for `documentStatus` values. Requires X-Partner-Api-Key and Bearer access token.\n\nPoll after a successful POST /partner-api/documents/upload using the documentId you supplied.\n\nRecommended throttle (exponential backoff):\n- Interval sequence: 3s → 6s → 12s → 24s → 60s (cap)\n- Minimum interval: 3 seconds (do not poll sub-second)\n- Maximum interval: 60 seconds once processing is underway\n- Reset backoff when documentStatus changes (optional optimization)\n\nStop polling when documentStatus is terminal:\n- Success: PROCESSED\n- Failure: ERROR, ERROR_OCR, ERROR_POST_PROCESSING, ERROR_CLASSIFICATION, ERROR_BAD_INPUT_DATA, ERROR_NOT_RECENT_1040, ERROR_UNSUPPORTED_FORM\n- Other: ARCHIVED\n\nSafety limits:\n- Typical processing completes in 1–10 minutes; flag for manual review if still in-progress after 30 minutes\n- Stop automatic polling after 2 hours and surface a timeout to the user\n- When polling many documents, cap parallel requests (e.g. 10 concurrent) and stagger starts\n- No dedicated partner-api rate limiter exists today, but backoff keeps load reasonable (~20 req/min per document)\n\nWebhooks will replace polling when available.",
              "type": "text/plain"
            },
            "url": {
              "path": [
                "partner-api",
                "documents",
                "status",
                ":id"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [],
              "variable": [
                {
                  "disabled": false,
                  "type": "any",
                  "value": "{{documentId}}",
                  "key": "id",
                  "description": "(Required) Your documentId from POST /partner-api/documents/upload"
                }
              ]
            },
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "GET",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{bearerToken}}"
                }
              ]
            }
          },
          "response": [
            {
              "id": "7fd66032-ee0a-4401-a06a-febbcf958707",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "documents",
                    "status",
                    ":id"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": [
                    {
                      "disabled": false,
                      "type": "any",
                      "value": "<string>",
                      "key": "id",
                      "description": "(Required) Your documentId from POST /partner-api/documents/upload"
                    }
                  ]
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: bearer",
                      "type": "text/plain"
                    },
                    "key": "Authorization",
                    "value": "Bearer <token>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "GET",
                "body": {}
              },
              "status": "OK",
              "code": 200,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"documentStatus\": \"PROCESSING\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "37376f17-3999-4ee0-9c9b-558a39c548c1",
              "name": "DocumentId is required",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "documents",
                    "status",
                    ":id"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": [
                    {
                      "disabled": false,
                      "type": "any",
                      "value": "<string>",
                      "key": "id",
                      "description": "(Required) Your documentId from POST /partner-api/documents/upload"
                    }
                  ]
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: bearer",
                      "type": "text/plain"
                    },
                    "key": "Authorization",
                    "value": "Bearer <token>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "GET",
                "body": {}
              },
              "status": "Bad Request",
              "code": 400,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 400,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/documents/status/doc_abc123\",\n  \"method\": \"GET\",\n  \"message\": \"DocumentId is required\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "5cde99f3-c87d-436d-aff2-948157c38034",
              "name": "Missing/Invalid API key or Unauthorized access token",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "documents",
                    "status",
                    ":id"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": [
                    {
                      "disabled": false,
                      "type": "any",
                      "value": "<string>",
                      "key": "id",
                      "description": "(Required) Your documentId from POST /partner-api/documents/upload"
                    }
                  ]
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: bearer",
                      "type": "text/plain"
                    },
                    "key": "Authorization",
                    "value": "Bearer <token>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "GET",
                "body": {}
              },
              "status": "Unauthorized",
              "code": 401,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 401,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/documents/status/doc_abc123\",\n  \"method\": \"GET\",\n  \"message\": \"Missing API key\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "8b4b9407-7bdb-45e7-aa1b-891c19e979da",
              "name": "Document not found",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "documents",
                    "status",
                    ":id"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": [
                    {
                      "disabled": false,
                      "type": "any",
                      "value": "<string>",
                      "key": "id",
                      "description": "(Required) Your documentId from POST /partner-api/documents/upload"
                    }
                  ]
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: bearer",
                      "type": "text/plain"
                    },
                    "key": "Authorization",
                    "value": "Bearer <token>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "GET",
                "body": {}
              },
              "status": "Not Found",
              "code": 404,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 404,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/documents/status/doc_abc123\",\n  \"method\": \"GET\",\n  \"message\": \"Document not found\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "d5ec354c-c044-4a82-9bfc-ff4a5ce87c9d",
              "name": "Error retrieving document status",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "documents",
                    "status",
                    ":id"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": [
                    {
                      "disabled": false,
                      "type": "any",
                      "value": "<string>",
                      "key": "id",
                      "description": "(Required) Your documentId from POST /partner-api/documents/upload"
                    }
                  ]
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: bearer",
                      "type": "text/plain"
                    },
                    "key": "Authorization",
                    "value": "Bearer <token>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "GET",
                "body": {}
              },
              "status": "Internal Server Error",
              "code": 500,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 500,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/documents/status/doc_abc123\",\n  \"method\": \"GET\",\n  \"message\": \"Error retrieving document status\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            }
          ],
          "event": [],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        }
      ],
      "event": []
    },
    {
      "id": "8d2d7cc4-89dc-4b91-a9eb-6bd32f11dcd1",
      "name": "Account",
      "description": {
        "content": "",
        "type": "text/plain"
      },
      "item": [
        {
          "id": "3d99620a-9260-42dd-b204-95592f4ac7f7",
          "name": "Get returns usage and entitlement for your account",
          "request": {
            "name": "Get returns usage and entitlement for your account",
            "description": {
              "content": "Returns usage counts and entitlement for the partner's active organization. lifecycleStage and trialReturnLimit semantics are documented on the 200 response schema. Requires X-Partner-Api-Key and Bearer access token.",
              "type": "text/plain"
            },
            "url": {
              "path": [
                "partner-api",
                "account",
                "returns-usage"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [],
              "variable": []
            },
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "GET",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{bearerToken}}"
                }
              ]
            }
          },
          "response": [
            {
              "id": "60182524-bc0b-474c-abdf-651718456a50",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "account",
                    "returns-usage"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: bearer",
                      "type": "text/plain"
                    },
                    "key": "Authorization",
                    "value": "Bearer <token>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "GET",
                "body": {}
              },
              "status": "OK",
              "code": 200,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"numReturnsUsed\": 5,\n  \"numReturnsAvailable\": 45,\n  \"numReturnsPurchased\": 50,\n  \"isTrialAccount\": false,\n  \"lifecycleStage\": \"customer\",\n  \"trialReturnLimit\": 3699.578579915226\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "2185735c-29db-4abe-ab72-637239c60267",
              "name": "Missing/Invalid API key or Unauthorized access token",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "account",
                    "returns-usage"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: bearer",
                      "type": "text/plain"
                    },
                    "key": "Authorization",
                    "value": "Bearer <token>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "GET",
                "body": {}
              },
              "status": "Unauthorized",
              "code": 401,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 401,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/account/returns-usage\",\n  \"method\": \"GET\",\n  \"message\": \"Missing API key\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "1adcf4e5-fc74-4087-bfec-fde68fb4aa8b",
              "name": "No active organization found for this partner, or no subscription found",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "account",
                    "returns-usage"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: bearer",
                      "type": "text/plain"
                    },
                    "key": "Authorization",
                    "value": "Bearer <token>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "GET",
                "body": {}
              },
              "status": "Not Found",
              "code": 404,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 404,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/account/returns-usage\",\n  \"method\": \"GET\",\n  \"message\": \"No active organization found for this partner\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "b06a9717-f843-4bd8-b588-3a2d923ee5ce",
              "name": "Failed to retrieve returns usage information",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "account",
                    "returns-usage"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: bearer",
                      "type": "text/plain"
                    },
                    "key": "Authorization",
                    "value": "Bearer <token>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "GET",
                "body": {}
              },
              "status": "Internal Server Error",
              "code": 500,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 500,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/account/returns-usage\",\n  \"method\": \"GET\",\n  \"message\": \"Failed to retrieve returns usage information\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            }
          ],
          "event": [],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        }
      ],
      "event": []
    },
    {
      "id": "2aced1cb-86ce-400c-bf85-8eba50bf7ee7",
      "name": "Extraction",
      "description": {
        "content": "",
        "type": "text/plain"
      },
      "item": [
        {
          "id": "cc68bf46-61ef-4506-8d07-c90cf6bbb5a1",
          "name": "1. Generate a pre-signed S3 URL for an extraction document upload",
          "request": {
            "name": "Generate a pre-signed S3 URL for an extraction document upload",
            "description": {
              "content": "Step 1. Returns a presigned URL — PUT the file to signed_url, then pass url as s3Url in POST /partner-api/extraction/documents. HMAC-signed (service account).",
              "type": "text/plain"
            },
            "url": {
              "path": [
                "partner-api",
                "extraction",
                "secure-link"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [],
              "variable": []
            },
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "POST",
            "auth": {
              "type": "noauth"
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"documentId\": \"{{documentId}}\",\n  \"documentName\": \"source-document-2025.pdf\",\n  \"mimeType\": \"application/pdf\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "id": "77eb3288-f27e-44d3-90a7-1315365234f1",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "extraction",
                    "secure-link"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: apikey",
                      "type": "text/plain"
                    },
                    "key": "x-partner-signature",
                    "value": "<API Key>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"documentId\": \"doc_abc123\",\n  \"documentName\": \"source-document-2025.pdf\",\n  \"mimeType\": \"application/pdf\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Created",
              "code": 201,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"signed_url\": \"https://bucket.s3.amazonaws.com/env/uuid_source-document-2025.pdf?X-Amz-...\",\n  \"url\": \"s3://bucket-name/env/uuid_source-document-2025.pdf\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "1565ab09-a7f7-45ec-bbbf-8c6134ae62a7",
              "name": "Request validation failed",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "extraction",
                    "secure-link"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: apikey",
                      "type": "text/plain"
                    },
                    "key": "x-partner-signature",
                    "value": "<API Key>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"documentId\": \"doc_abc123\",\n  \"documentName\": \"source-document-2025.pdf\",\n  \"mimeType\": \"application/pdf\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 400,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/extraction/secure-link\",\n  \"method\": \"POST\",\n  \"message\": [\n    \"documentName should not be empty\"\n  ]\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "c45a848b-18ba-46bb-8f27-3ce12d5e88ed",
              "name": "Missing or invalid HMAC signature",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "extraction",
                    "secure-link"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: apikey",
                      "type": "text/plain"
                    },
                    "key": "x-partner-signature",
                    "value": "<API Key>"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"documentId\": \"doc_abc123\",\n  \"documentName\": \"source-document-2025.pdf\",\n  \"mimeType\": \"application/pdf\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Unauthorized",
              "code": 401,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "text/plain"
                }
              ],
              "body": "",
              "cookie": [],
              "_postman_previewlanguage": "text"
            }
          ],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "if (pm.response.code === 201) {",
                  "  const json = pm.response.json();",
                  "  if (json.signed_url) pm.collectionVariables.set('signedUrl', json.signed_url);",
                  "  if (json.url) pm.collectionVariables.set('s3Url', json.url);",
                  "}"
                ]
              }
            }
          ],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        },
        {
          "id": "58598c5c-c204-4b64-bb12-e0ac528c7506",
          "name": "2. Upload file to S3 (presigned URL)",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/pdf",
                "description": "MIME type of the file being uploaded"
              }
            ],
            "body": {
              "mode": "file",
              "file": {}
            },
            "url": "{{signedUrl}}",
            "description": "Step 2 of document upload (not part of the Juno API). PUT file bytes directly to the presigned URL from '1. Generate a pre-signed S3 URL'. On success, call '3. Register an uploaded document' with s3Url set to the url field from step 1."
          },
          "response": [],
          "event": []
        },
        {
          "id": "e999f5df-5a57-49e6-bb7f-89c7c471e569",
          "name": "3. Register an uploaded source document and start extraction",
          "request": {
            "name": "Register an uploaded source document and start extraction",
            "description": {
              "content": "Step 2. Registers the S3 object and starts the extraction pipeline. See documentType for supported source document types. Idempotent on externalDocumentId. HMAC-signed (service account). Optionally supply client context (externalClientId, taxYear, clientFirstName, clientLastName — all four together) to group documents under one client and tax preparation per (externalClientId, taxYear); omit all four to keep the default per-document behavior. Supplying only some of the four returns 400.",
              "type": "text/plain"
            },
            "url": {
              "path": [
                "partner-api",
                "extraction",
                "documents"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [],
              "variable": []
            },
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "POST",
            "auth": {
              "type": "noauth"
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"externalDocumentId\": \"{{documentId}}\",\n  \"s3Url\": \"{{s3Url}}\",\n  \"documentType\": \"BROKERAGE\",\n  \"callbackUrl\": \"https://example.com/callbacks/doc_abc123\",\n  \"externalClientId\": \"client_abc123\",\n  \"taxYear\": 2025,\n  \"clientFirstName\": \"Jane\",\n  \"clientLastName\": \"Doe\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "id": "9e52d4de-2248-44ce-8122-16ce98161012",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "extraction",
                    "documents"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: apikey",
                      "type": "text/plain"
                    },
                    "key": "x-partner-signature",
                    "value": "<API Key>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"externalDocumentId\": \"doc_abc123\",\n  \"s3Url\": \"s3://bucket-name/env/uuid_source-document-2025.pdf\",\n  \"documentType\": \"BROKERAGE\",\n  \"callbackUrl\": \"https://example.com/callbacks/doc_abc123\",\n  \"externalClientId\": \"client_abc123\",\n  \"taxYear\": 2025,\n  \"clientFirstName\": \"Jane\",\n  \"clientLastName\": \"Doe\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Created",
              "code": 201,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"id\": \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\",\n  \"externalDocumentId\": \"doc_abc123\",\n  \"taxDocumentId\": \"b2c3d4e5-f6a7-8901-bcde-f12345678901\",\n  \"status\": \"UPLOADED\",\n  \"createdAt\": \"2026-06-24T12:00:00.000Z\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "e674e5c0-41cb-409a-b8ee-9c771183c37b",
              "name": "Validation failed or unsupported document type",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "extraction",
                    "documents"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: apikey",
                      "type": "text/plain"
                    },
                    "key": "x-partner-signature",
                    "value": "<API Key>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"externalDocumentId\": \"doc_abc123\",\n  \"s3Url\": \"s3://bucket-name/env/uuid_source-document-2025.pdf\",\n  \"documentType\": \"BROKERAGE\",\n  \"callbackUrl\": \"https://example.com/callbacks/doc_abc123\",\n  \"externalClientId\": \"client_abc123\",\n  \"taxYear\": 2025,\n  \"clientFirstName\": \"Jane\",\n  \"clientLastName\": \"Doe\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 400,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/extraction/documents\",\n  \"method\": \"POST\",\n  \"message\": [\n    \"s3Url should not be empty\"\n  ]\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "b170635a-73e7-440a-9be9-ff7632389e5e",
              "name": "Missing or invalid HMAC signature",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "extraction",
                    "documents"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": []
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: apikey",
                      "type": "text/plain"
                    },
                    "key": "x-partner-signature",
                    "value": "<API Key>"
                  }
                ],
                "method": "POST",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"externalDocumentId\": \"doc_abc123\",\n  \"s3Url\": \"s3://bucket-name/env/uuid_source-document-2025.pdf\",\n  \"documentType\": \"BROKERAGE\",\n  \"callbackUrl\": \"https://example.com/callbacks/doc_abc123\",\n  \"externalClientId\": \"client_abc123\",\n  \"taxYear\": 2025,\n  \"clientFirstName\": \"Jane\",\n  \"clientLastName\": \"Doe\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Unauthorized",
              "code": 401,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "text/plain"
                }
              ],
              "body": "",
              "cookie": [],
              "_postman_previewlanguage": "text"
            }
          ],
          "event": [],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        },
        {
          "id": "ef49fe87-5dae-407d-b84d-d754c1d6ad1f",
          "name": "4. Get the extraction status of a document",
          "request": {
            "name": "Get the extraction status of a document",
            "description": {
              "content": "Returns the current processing state for a document you registered. Path parameter is your externalDocumentId. HMAC-signed (service account).",
              "type": "text/plain"
            },
            "url": {
              "path": [
                "partner-api",
                "extraction",
                "documents",
                ":externalDocumentId"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [],
              "variable": [
                {
                  "disabled": false,
                  "type": "any",
                  "value": "{{documentId}}",
                  "key": "externalDocumentId",
                  "description": "(Required) "
                }
              ]
            },
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "GET",
            "auth": {
              "type": "noauth"
            }
          },
          "response": [
            {
              "id": "aa4dd8b4-a355-4e80-81bf-3d92c9a2f6f5",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "extraction",
                    "documents",
                    ":externalDocumentId"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": [
                    {
                      "disabled": false,
                      "type": "any",
                      "value": "doc_abc123",
                      "key": "externalDocumentId",
                      "description": "(Required) "
                    }
                  ]
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: apikey",
                      "type": "text/plain"
                    },
                    "key": "x-partner-signature",
                    "value": "<API Key>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "GET",
                "body": {}
              },
              "status": "OK",
              "code": 200,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"documentStatus\": \"PROCESSING\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            },
            {
              "id": "0fb893d2-4072-4d0f-93e5-b0bf68238d5a",
              "name": "Missing or invalid HMAC signature",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "extraction",
                    "documents",
                    ":externalDocumentId"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": [
                    {
                      "disabled": false,
                      "type": "any",
                      "value": "doc_abc123",
                      "key": "externalDocumentId",
                      "description": "(Required) "
                    }
                  ]
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: apikey",
                      "type": "text/plain"
                    },
                    "key": "x-partner-signature",
                    "value": "<API Key>"
                  }
                ],
                "method": "GET",
                "body": {}
              },
              "status": "Unauthorized",
              "code": 401,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "text/plain"
                }
              ],
              "body": "",
              "cookie": [],
              "_postman_previewlanguage": "text"
            },
            {
              "id": "d51254cc-56a6-4c0b-82c7-ad723a54dc6e",
              "name": "Document not found",
              "originalRequest": {
                "url": {
                  "path": [
                    "partner-api",
                    "extraction",
                    "documents",
                    ":externalDocumentId"
                  ],
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "query": [],
                  "variable": [
                    {
                      "disabled": false,
                      "type": "any",
                      "value": "doc_abc123",
                      "key": "externalDocumentId",
                      "description": "(Required) "
                    }
                  ]
                },
                "header": [
                  {
                    "description": {
                      "content": "Added as a part of security scheme: apikey",
                      "type": "text/plain"
                    },
                    "key": "x-partner-signature",
                    "value": "<API Key>"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "method": "GET",
                "body": {}
              },
              "status": "Not Found",
              "code": 404,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 404,\n  \"timestamp\": \"2026-06-08T12:00:00.000Z\",\n  \"path\": \"/partner-api/extraction/documents/doc_abc123\",\n  \"method\": \"GET\",\n  \"message\": \"Document not found\"\n}",
              "cookie": [],
              "_postman_previewlanguage": "json"
            }
          ],
          "event": [],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        }
      ],
      "event": []
    }
  ],
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "type": "text/javascript",
        "exec": [
          "const CryptoJS = require('crypto-js');",
          "",
          "const partnerApiKey = pm.collectionVariables.get('partnerApiKey');",
          "if (partnerApiKey) {",
          "  pm.request.headers.upsert({ key: 'X-Partner-Api-Key', value: partnerApiKey });",
          "}",
          "",
          "const requestPath = pm.request.url.getPath();",
          "const isExtraction = requestPath.includes('/partner-api/extraction/');",
          "",
          "if (isExtraction) {",
          "  const signingSecret = pm.collectionVariables.get('signingSecret');",
          "  if (signingSecret) {",
          "    const timestamp = String(Date.now());",
          "    const method = (pm.request.method || 'GET').toUpperCase();",
          "    let rawBody = '';",
          "    if (pm.request.body && pm.request.body.mode === 'raw' && pm.request.body.raw) {",
          "      rawBody = pm.variables.replaceIn(pm.request.body.raw);",
          "    }",
          "    const bodyHash = CryptoJS.SHA256(rawBody).toString(CryptoJS.enc.Hex);",
          "    const signingString = [method, requestPath, bodyHash, timestamp].join('\\n');",
          "    const signature = CryptoJS.HmacSHA256(signingString, signingSecret).toString(",
          "      CryptoJS.enc.Base64,",
          "    );",
          "    pm.request.headers.upsert({ key: 'X-Partner-Timestamp', value: timestamp });",
          "    pm.request.headers.upsert({ key: 'X-Partner-Signature', value: signature });",
          "  }",
          "} else {",
          "  const accessToken = pm.collectionVariables.get('accessToken');",
          "  if (accessToken) {",
          "    const needsBearer =",
          "      requestPath.includes('/partner-api/documents/') ||",
          "      requestPath.includes('/partner-api/account/');",
          "    if (needsBearer) {",
          "      pm.request.headers.upsert({",
          "        key: 'Authorization',",
          "        value: 'Bearer ' + accessToken,",
          "      });",
          "    }",
          "  }",
          "}"
        ]
      }
    }
  ],
  "variable": [
    {
      "key": "baseUrl",
      "value": "https://api-stg.juno.tax",
      "type": "string"
    },
    {
      "key": "partnerApiKey",
      "value": "",
      "type": "string"
    },
    {
      "key": "accessToken",
      "value": "",
      "type": "string"
    },
    {
      "key": "refreshToken",
      "value": "",
      "type": "string"
    },
    {
      "key": "signingSecret",
      "value": "",
      "type": "string"
    },
    {
      "key": "documentId",
      "value": "doc_abc123",
      "type": "string"
    },
    {
      "key": "signedUrl",
      "value": "",
      "type": "string"
    },
    {
      "key": "s3Url",
      "value": "",
      "type": "string"
    }
  ],
  "info": {
    "_postman_id": "59360c7f-581b-466e-ba2e-679d009faea7",
    "name": "Juno Partner API",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
    "description": {
      "type": "text/plain",
      "content": "The Juno Partner API supports user-linked document workflows and service-account source-document extraction.\n\nEach endpoint documents its own request schema, response shapes, enum values, and error examples. All errors share a standard envelope: { statusCode, timestamp, path, method, message } — identify errors by HTTP status and message text.\n\nAuthentication:\n- User-linked Documents / Account — X-Partner-Api-Key + Authorization Bearer (JWT from onboarding)\n- Extraction (service account) — X-Partner-Api-Key + X-Partner-Timestamp + X-Partner-Signature (HMAC; no JWT)\n- Hosts: api.juno.tax for partner API calls; app.juno.tax for user browser onboarding redirects\n\nOutbound webhooks: Juno POSTs a JSON array of events to your subscribed URL, signed with X-Juno-Signature / X-Juno-Request-Timestamp. Processed-document results use type taxDocument.processed with a data object (externalDocumentId, documentStatus, outcome, extractedFields or resultsUrl). See the integration guide for signing, payload examples, and the extraction upload sequence.\n\nPostman setup:\n1. Import juno-partner-api-sandbox.postman_environment.json and select it.\n2. User-linked flows: set partnerApiKey, accessToken, and refreshToken.\n3. Extraction (HMAC): set partnerApiKey and signingSecret — the pre-request script signs /partner-api/extraction/* automatically.\n4. Document upload flow: 1. secure-link → 2. PUT to S3 → 3. register/upload → 4. status (or wait for taxDocument.processed webhook).\n5. Refresh and Authenticate requests auto-save tokens to collection variables."
    }
  }
}