---
title: "Identity API"
url: "https://developer-staging.agentsync.io/apis/identity/versions/1ed33a2c-924a-434c-9643-fbc531dea1b8"
---

# Identity API

OpenAPI specification document.

````json
{"openapi":"3.0.1","info":{"title":"Identity API","description":"Manage producer identities — persons, firms, and their addresses, phone numbers, bank accounts,\nand insurance policies.\n\n## Authentication\n\nEvery endpoint requires an OAuth2 **client credentials** token. Request one using the client ID and\nsecret issued to you, then send it as `Authorization: Bearer <token>`.\n\n**Use the token endpoint that matches the environment you are calling** — a sandbox token is not valid\nagainst production, or vice versa:\n\n| Environment | API base URL | Token endpoint |\n|---|---|---|\n| Sandbox | `https://api.sandbox.agentsync.io/id` | `https://auth.sandbox.agentsync.io/oauth2/token` |\n| Production | `https://api.agentsync.io/id` | `https://auth.agentsync.io/oauth2/token` |\n\nThe machine-readable `tokenUrl` in this document is the **sandbox** endpoint, because OpenAPI 3.0 allows\nonly one token URL per flow. If you generate a client from this spec and point it at production, override\nthe token endpoint to the production URL above.\n\nTwo scopes govern access: `identity.profiles.read` for all read operations and\n`identity.profiles.write` for creates, updates, and deletes. A token missing the required scope\nreturns `403` with code `unauthorized_scope`.\n\n## Pagination\n\nList endpoints use opaque token-based pagination. Pass `page_size` to set the page size and\n`page_token` to continue from a previous response. `page_size` defaults to 25 when omitted; a value\noutside `[1, 250]` is rejected with `400` rather than clamped, so validate before sending.\n\nResponses wrap results in an envelope:\n\n```json\n{\n  \"items\": [ ... ],\n  \"page\": { \"size\": 25, \"nextToken\": \"eyJ2IjoxLCJrIjp...\" }\n}\n```\n\n`page.size` is the number of items actually returned, so it is `0` on an empty result and may be\nsmaller than the `page_size` you requested on the last page. Keep requesting while\n`page.nextToken` is non-null; it is `null` on the final page. Treat the token as opaque — its\nformat is server-controlled and may change without an API version bump.\n\n## Errors\n\nErrors share one shape across every endpoint:\n\n```json\n{\n  \"message\": \"Validation failed\",\n  \"details\": [ { \"param\": \"email\", \"message\": \"must not be blank\" } ],\n  \"code\": \"validation_failed\"\n}\n```\n\nBranch on `code`, which is stable and machine-readable — never on `message`, which is a\nhuman-readable summary and may be reworded. `details` carries per-field validation errors on\n`400` responses and is empty otherwise.\n\n## Rate limiting\n\nEvery response carries `ratelimit-limit`, `ratelimit-remaining`, and `ratelimit-reset` headers.\nOn a `429`, use the `Retry-After` header directly as your retry delay — it already accounts for\nserver-side backoff. Because the limit is a sliding window, `ratelimit-reset` is a hint rather\nthan a hard reset point; retrying at exactly that instant may still return `429` under sustained\nload.\n","version":"v1.275.8"},"servers":[{"url":"https://api.sandbox.agentsync.io/id","description":"Sandbox server"},{"url":"https://api.agentsync.io/id","description":"Production server"}],"security":[{"oauth2":[]}],"tags":[{"name":"Bank Accounts","description":"Operations for managing bank accounts"},{"name":"Firms","description":"Operations for managing firm identities"},{"name":"Persons","description":"Operations for managing person identities"},{"name":"Addresses","description":"Operations for managing addresses"},{"name":"Phones","description":"Operations for managing phone numbers"},{"name":"Insurance Policies","description":"Operations for managing E&O insurance policies"}],"paths":{"/v2/bank-accounts/{bankAccountId}":{"get":{"summary":"Retrieve bank account","description":"Returns a single bank account by ID. The `number` field contains the full account number — use this endpoint when you need the complete value for payment processing or verification. For reconciliation use cases where only the last four digits are sufficient, prefer `GET /v2/bank-accounts` which returns all accounts with numbers masked to `****<last4>`.\n\nReturns 404 if the bank account does not exist or is not visible to the authenticated customer. A 403 is returned only when the caller's token lacks the required scope; cross-customer access returns 404, not 403.\n","operationId":"getBankAccountV2","tags":["Bank Accounts"],"security":[{"oauth2":["identity.profiles.read"]}],"parameters":[{"$ref":"#/components/parameters/BankAccountIdParam"}],"responses":{"200":{"description":"Bank account retrieved successfully.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BankAccountFullResponse"}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}},"delete":{"summary":"Delete bank account","description":"Permanently deletes a bank account. Returns 404 if the bank account does not exist or is not accessible to the caller.\n","operationId":"deleteBankAccountV2","tags":["Bank Accounts"],"security":[{"oauth2":["identity.profiles.write"]}],"parameters":[{"$ref":"#/components/parameters/BankAccountIdParam"}],"responses":{"204":{"description":"Bank account deleted successfully","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}},"put":{"summary":"Update bank account","description":"Updates an existing bank account scoped to the authenticated customer. Returns the updated record with the account number masked.","operationId":"updateBankAccountV2","tags":["Bank Accounts"],"security":[{"oauth2":["identity.profiles.write"]}],"parameters":[{"$ref":"#/components/parameters/BankAccountIdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBankAccountRequest"}}}},"responses":{"200":{"description":"Bank account updated successfully","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BankAccountResponse"}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}}},"/v2/bank-accounts":{"get":{"summary":"List bank accounts for the authenticated customer","description":"Returns every bank account (person-owned or firm-owned) visible to the authenticated customer, paginated by opaque continuation token. Use this endpoint to reconcile bank accounts across all producers in a customer's account without iterating known producer IDs. Account numbers are masked to ****<last4>; the unmasked value is reachable only via GET /v2/bank-accounts/{id} behind an elevated scope.\n","operationId":"listV2BankAccounts","tags":["Bank Accounts"],"security":[{"oauth2":["identity.profiles.read"]}],"parameters":[{"$ref":"#/components/parameters/PageToken"},{"$ref":"#/components/parameters/PageSize"},{"name":"updated_since","in":"query","required":false,"description":"RFC3339 UTC timestamp (e.g. 2026-05-21T12:00:00Z). When supplied, filters to bank accounts whose underlying record was modified at or after this instant.\n","schema":{"type":"string","format":"date-time","example":"2026-05-01T00:00:00Z"}}],"responses":{"200":{"description":"A page of bank accounts visible to the authenticated customer.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"type":"object","required":["items","page"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/BankAccountListItemV2"}},"page":{"$ref":"#/components/schemas/Page"}}}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}}},"/v2/persons/{personId}/bank-accounts":{"get":{"summary":"List bank accounts for a person","description":"Returns bank accounts belonging to the specified person and visible to the authenticated customer, paginated by opaque continuation token. Account numbers are masked to ****<last4>.\n","operationId":"listPersonBankAccountsV2","tags":["Bank Accounts"],"security":[{"oauth2":["identity.profiles.read"]}],"parameters":[{"$ref":"#/components/parameters/PersonIdParam"},{"$ref":"#/components/parameters/PageToken"},{"$ref":"#/components/parameters/PageSize"}],"responses":{"200":{"description":"A page of bank accounts belonging to the person.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"type":"object","required":["items","page"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/BankAccountListItemV2"}},"page":{"$ref":"#/components/schemas/Page"}}}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}},"post":{"summary":"Create bank account for person","description":"Creates a new bank account for a person","operationId":"createPersonBankAccount","tags":["Bank Accounts"],"security":[{"oauth2":["identity.profiles.write"]}],"parameters":[{"$ref":"#/components/parameters/PersonIdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBankAccountRequest"}}}},"responses":{"201":{"description":"Bank account created successfully","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BankAccountResponse"}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}}},"/v2/firms/{firmId}/bank-accounts":{"get":{"summary":"List bank accounts for a firm","description":"Returns bank accounts belonging to the specified firm and visible to the authenticated customer, paginated by opaque continuation token. Account numbers are masked to ****<last4>.\n","operationId":"listFirmBankAccountsV2","tags":["Bank Accounts"],"security":[{"oauth2":["identity.profiles.read"]}],"parameters":[{"$ref":"#/components/parameters/FirmIdParam"},{"$ref":"#/components/parameters/PageToken"},{"$ref":"#/components/parameters/PageSize"}],"responses":{"200":{"description":"A page of bank accounts belonging to the firm.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"type":"object","required":["items","page"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/BankAccountListItemV2"}},"page":{"$ref":"#/components/schemas/Page"}}}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}},"post":{"summary":"Create bank account for firm","description":"Creates a new bank account for a firm scoped to the authenticated customer. Returns the created record with the account number masked.","operationId":"createFirmBankAccountV2","tags":["Bank Accounts"],"security":[{"oauth2":["identity.profiles.write"]}],"parameters":[{"$ref":"#/components/parameters/FirmIdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBankAccountRequest"}}}},"responses":{"201":{"description":"Bank account created successfully","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BankAccountResponse"}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}}},"/v2/insurance-policies/{policyId}":{"get":{"summary":"Get insurance policy by ID","description":"Returns a single E&O insurance policy by ID, scoped to the authenticated customer. Includes a presigned certificate download URL when a file has been uploaded (TTL 10 minutes).","operationId":"getInsurancePolicyV2","tags":["Insurance Policies"],"security":[{"oauth2":["identity.profiles.read"]}],"parameters":[{"name":"policyId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Unique identifier of the insurance policy."}],"responses":{"200":{"description":"Insurance policy retrieved successfully.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsurancePolicyV2"}}}},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}},"delete":{"summary":"Delete insurance policy","description":"Permanently deletes an E&O insurance policy by ID, scoped to the authenticated customer. Returns 404 if the policy does not exist or is not accessible to the caller. A 403 is returned only when the caller's token lacks the required scope; cross-customer access returns 404, not 403.\n","operationId":"deleteInsurancePolicyV2","tags":["Insurance Policies"],"security":[{"oauth2":["identity.profiles.write"]}],"parameters":[{"$ref":"#/components/parameters/InsurancePolicyIdParam"}],"responses":{"204":{"description":"Insurance policy deleted successfully.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}}},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}},"put":{"summary":"Update insurance policy","description":"Updates an existing E&O insurance policy by ID. The policy must be owned by the authenticated customer; unknown or cross-customer IDs return 404.","operationId":"updateInsurancePolicyV2","tags":["Insurance Policies"],"security":[{"oauth2":["identity.profiles.write"]}],"parameters":[{"$ref":"#/components/parameters/InsurancePolicyIdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateInsurancePolicyRequest"}}}},"responses":{"200":{"description":"Insurance policy updated successfully.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsurancePolicyV2"}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}}},"/v2/insurance-policies/{policyId}/files":{"delete":{"summary":"Delete insurance policy certificate file","description":"Deletes the E&O certificate file attached to an insurance policy, scoped to the authenticated customer. The policy record itself is preserved; `hasFile` becomes `false` and the presigned certificate URL is no longer returned. Returns 204 whether or not a file was attached (deleting a file that does not exist is a no-op). Returns 404 if the policy does not exist or is not accessible to the caller. A 403 is returned only when the caller's token lacks the required scope; cross-customer access returns 404, not 403.\n","operationId":"deleteInsurancePolicyFileV2","tags":["Insurance Policies"],"security":[{"oauth2":["identity.profiles.write"]}],"parameters":[{"$ref":"#/components/parameters/InsurancePolicyIdParam"}],"responses":{"204":{"description":"Certificate file deleted successfully (or no file was attached).","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}}},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}},"post":{"summary":"Upload insurance policy certificate file","description":"Uploads (or replaces) the E&O certificate file for a policy, scoped to the authenticated customer. Accepts a single multipart/form-data `file` part (PDF, JPEG, or PNG). On success the policy's `hasFile` becomes true and the response includes a presigned `certificateUrl` (TTL 10 minutes). Returns 404 if the policy does not exist or is not accessible to the caller; a 403 is returned only when the caller's token lacks the required scope (cross-customer access returns 404, not 403).\n","operationId":"uploadInsurancePolicyFileV2","tags":["Insurance Policies"],"security":[{"oauth2":["identity.profiles.write"]}],"parameters":[{"$ref":"#/components/parameters/InsurancePolicyIdParam"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary","description":"The certificate file to upload (PDF, JPEG, or PNG)."}}}}}},"responses":{"200":{"description":"File uploaded successfully; returns the updated insurance policy.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsurancePolicyV2"}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"415":{"$ref":"#/components/responses/V2UnsupportedMediaType"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}}},"/v2/persons/{personId}/insurance-policies":{"get":{"summary":"List insurance policies for person","description":"Returns a keyset-paginated list of E&O insurance policies for a person, scoped to the authenticated customer.","operationId":"listPersonInsurancePoliciesV2","tags":["Insurance Policies"],"security":[{"oauth2":["identity.profiles.read"]}],"parameters":[{"$ref":"#/components/parameters/PersonIdParam"},{"$ref":"#/components/parameters/PageToken"},{"$ref":"#/components/parameters/PageSize"}],"responses":{"200":{"description":"Paginated list of insurance policies.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"type":"object","required":["items","page"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/InsurancePolicyV2"}},"page":{"$ref":"#/components/schemas/Page"}}}}}},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}},"post":{"summary":"Create insurance policy for person","description":"Creates a new E&O insurance policy for a person.","operationId":"createPersonInsurancePolicyV2","tags":["Insurance Policies"],"security":[{"oauth2":["identity.profiles.write"]}],"parameters":[{"$ref":"#/components/parameters/PersonIdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInsurancePolicyRequest"}}}},"responses":{"201":{"description":"Insurance policy created successfully.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsurancePolicyV2"}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}}},"/v2/firms/{firmId}/insurance-policies":{"get":{"summary":"List insurance policies for firm","description":"Returns a keyset-paginated list of E&O insurance policies for a firm, scoped to the authenticated customer.","operationId":"listFirmInsurancePoliciesV2","tags":["Insurance Policies"],"security":[{"oauth2":["identity.profiles.read"]}],"parameters":[{"$ref":"#/components/parameters/FirmIdParam"},{"$ref":"#/components/parameters/PageToken"},{"$ref":"#/components/parameters/PageSize"}],"responses":{"200":{"description":"Paginated list of insurance policies.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"type":"object","required":["items","page"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/InsurancePolicyV2"}},"page":{"$ref":"#/components/schemas/Page"}}}}}},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}},"post":{"summary":"Create insurance policy for firm","description":"Creates a new E&O insurance policy for a firm.","operationId":"createFirmInsurancePolicyV2","tags":["Insurance Policies"],"security":[{"oauth2":["identity.profiles.write"]}],"parameters":[{"$ref":"#/components/parameters/FirmIdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInsurancePolicyRequest"}}}},"responses":{"201":{"description":"Insurance policy created successfully.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsurancePolicyV2"}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}}},"/v2/firms":{"get":{"summary":"List firms (customer-scoped, keyset-paginated)","description":"Returns a keyset-paginated list of firms visible to the authenticated customer, sorted by (modifiedDate ASC, id ASC). Optionally filters to records modified on or after `updated_since` (RFC3339 instant, inclusive).\n\nThe FEIN is always masked to ****<last4>. Empty results return `items: []`, `page.size: 0`, `nextToken: null`.\n\nReturns 403 when the caller's token lacks the required scope.\n","operationId":"listFirmsV2","tags":["Firms"],"security":[{"oauth2":["identity.profiles.read"]}],"parameters":[{"$ref":"#/components/parameters/PageToken"},{"$ref":"#/components/parameters/PageSize"},{"name":"updated_since","in":"query","required":false,"description":"RFC3339 timestamp. When supplied, only firms modified at or after this instant are returned.","schema":{"type":"string","format":"date-time","example":"2024-01-15T10:30:00Z"}}],"responses":{"200":{"description":"Firm list retrieved successfully.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FirmV2List"}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}}},"/v2/firms/{firmId}":{"get":{"summary":"Get a firm by ID","description":"Returns a single firm visible to the authenticated customer. The FEIN is always masked to ****<last4> and never returned in full here; use GET /v2/firms/{firmId}/fein (audited) for the full value.\n\nReturns 404 if the firm does not exist or is not visible to the authenticated customer. A 403 is returned only when the caller's token lacks the required scope; cross-customer access returns 404, not 403.\n","operationId":"getFirmV2","tags":["Firms"],"security":[{"oauth2":["identity.profiles.read"]}],"parameters":[{"$ref":"#/components/parameters/FirmIdParam"}],"responses":{"200":{"description":"Firm retrieved successfully.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FirmV2"}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}},"put":{"summary":"Update a firm by ID","description":"Updates mutable fields on a firm visible to the authenticated customer. The fields `npn` and `fein` are immutable and cannot be changed via this endpoint. Omitted fields leave the stored value unchanged (partial update).\n\nReturns 404 if the firm does not exist or is not visible to the authenticated customer. A 403 is returned only when the caller's token lacks the required scope; cross-customer access returns 404, not 403.\n","operationId":"updateFirmV2","tags":["Firms"],"security":[{"oauth2":["identity.profiles.write"]}],"parameters":[{"$ref":"#/components/parameters/FirmIdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateFirmRequest"}}}},"responses":{"200":{"description":"Firm updated successfully.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FirmV2"}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}}},"/v2/firms/{firmId}/fein":{"get":{"summary":"Retrieve a firm's unmasked FEIN","description":"Returns the full, unmasked Federal Employer Identification Number for the specified firm. The FEIN is masked everywhere else in the API and returned in full only by this endpoint. Every access is recorded in a durable audit log. Cross-customer or unknown ids return 404 (never 403) so resource existence is not leaked across customer boundaries.\n","operationId":"getFirmFein","tags":["Firms"],"security":[{"oauth2":["identity.profiles.read"]}],"parameters":[{"$ref":"#/components/parameters/FirmIdParam"}],"responses":{"200":{"description":"Full unmasked FEIN retrieved successfully.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeinDto"}}}},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}}},"/v2/persons":{"post":{"summary":"Create a person","description":"Creates a new producer identity and associates them with the authenticated customer. The new person is immediately visible to the caller's organization.\n\nWhen `sendInvite` is omitted or `false`, the person is created without sending an email invitation. Set `sendInvite: true` to trigger the same invite email as the V1 `?sendInvite=true` path.\n\nReturns 400 when required fields are missing or field values fail validation.\n","operationId":"createPersonV2","tags":["Persons"],"security":[{"oauth2":["identity.profiles.write"]}],"parameters":[{"$ref":"#/components/parameters/IdempotencyKeyParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePersonRequest"}}}},"responses":{"201":{"description":"Person created successfully.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonV2"}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}},"get":{"summary":"List persons","description":"Returns persons paginated by opaque continuation token, ordered by (modifiedDate, id) ascending. Supply `updated_since` to fetch only records modified at or after a given timestamp, or `firm_id` to restrict results to persons associated with a specific firm.\n\nReturns 404 if `firm_id` is supplied but is not owned by your organization. Returns 401 when the request carries no token and 403 when the token lacks the required scope.\n","operationId":"listV2Persons","tags":["Persons"],"security":[{"oauth2":["identity.profiles.read"]}],"parameters":[{"$ref":"#/components/parameters/PageToken"},{"$ref":"#/components/parameters/PageSize"},{"name":"updated_since","in":"query","required":false,"description":"RFC3339 UTC timestamp (e.g. 2026-06-01T00:00:00Z). When supplied, filters to persons whose record was modified at or after this instant (inclusive).\n","schema":{"type":"string","format":"date-time","example":"2026-06-01T00:00:00Z"}},{"name":"firm_id","in":"query","required":false,"description":"UUID of a firm. When supplied, restricts the result to persons associated with that firm. Returns 404 if the firm is not visible to the authenticated customer (never 403, so firm existence is not leaked across customer boundaries).\n","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}}],"responses":{"200":{"description":"A page of persons.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"type":"object","required":["items","page"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PersonListItemV2"}},"page":{"$ref":"#/components/schemas/Page"}}}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}}},"/v2/persons/{personId}":{"get":{"summary":"Get a person by ID","description":"Returns the customer-facing identity for the specified person. The person must be owned by the authenticated customer. SSN is masked — only the last four digits are present via `ssnLast4`. The full unmasked SSN is available only via `GET /v2/persons/{personId}/ssn`.\n\nReturns 404 if the person does not exist or is not visible to the authenticated customer.\n","operationId":"getPersonV2","tags":["Persons"],"security":[{"oauth2":["identity.profiles.read"]}],"parameters":[{"$ref":"#/components/parameters/PersonIdParam"}],"responses":{"200":{"description":"Person retrieved successfully.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonV2"}}}},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}},"put":{"summary":"Update a person","description":"Partially updates the specified person's identity fields. Only the fields present in the request body are applied — omitted fields retain their existing values. The person must be owned by the authenticated customer.\n\nReturns 404 if the person does not exist or is not visible to the authenticated customer (cross-customer access returns 404, not 403).\n","operationId":"updatePersonV2","tags":["Persons"],"security":[{"oauth2":["identity.profiles.write"]}],"parameters":[{"$ref":"#/components/parameters/PersonIdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePersonRequest"}}}},"responses":{"200":{"description":"Person updated successfully.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonV2"}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}}},"/v2/persons/{personId}/ssn":{"get":{"summary":"Retrieve a person's unmasked SSN","description":"Returns the full, unmasked Social Security Number for the specified person. The SSN is masked everywhere else in the API and returned in full only by this endpoint. Every access is recorded in a durable audit log.\n\nReturns 404 if the person does not exist, is not visible to the authenticated customer, or has no SSN on record. A 403 is returned only when the caller's token lacks the required scope; cross-customer access returns 404, not 403.\n","operationId":"getPersonSsnV2","tags":["Persons"],"security":[{"oauth2":["identity.profiles.read"]}],"parameters":[{"$ref":"#/components/parameters/PersonIdParam"}],"responses":{"200":{"description":"SSN retrieved successfully.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SsnResponse"}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}}},"/v2/persons/{personId}/firms":{"post":{"summary":"Associate a person with a firm","description":"Associates an existing person with an existing firm. This is a distinct operation from creating either resource — it only links a person to a firm the caller already owns. Both the person and the firm must be visible to the authenticated customer; if either is unknown or belongs to another customer the response is 404 (never 403), so resource existence is not leaked across customer boundaries.\n\nWhen `role` is omitted, it defaults to `PRINCIPAL`. Re-associating the same person and firm is idempotent and returns 201 with the current association.\n","operationId":"associatePersonWithFirmV2","tags":["Persons"],"security":[{"oauth2":["identity.profiles.write"]}],"parameters":[{"$ref":"#/components/parameters/PersonIdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssociateFirmRequestV2"}}}},"responses":{"201":{"description":"Association created.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonFirmV2"}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}}},"/v2/addresses/{addressId}":{"delete":{"summary":"Delete an address by ID","description":"Deletes a single address by its ID, scoped to the authenticated customer.\n\nReturns 404 if the address does not exist or is not visible to the authenticated customer. A 403 is returned only when the caller's token lacks the required scope; cross-customer access returns 404, not 403.\n","operationId":"deleteAddressByIdV2","tags":["Addresses"],"security":[{"oauth2":["identity.profiles.write"]}],"parameters":[{"$ref":"#/components/parameters/AddressIdParam"}],"responses":{"204":{"description":"Address deleted successfully.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}}},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}},"put":{"summary":"Update an address by ID","description":"Updates a single address by its ID, scoped to the authenticated customer.\n\nReturns 404 if the address does not exist or is not visible to the authenticated customer. A 403 is returned only when the caller's token lacks the required scope; cross-customer access returns 404, not 403. Returns 400 when the request body fails validation (V2 error shape).\n","operationId":"updateAddressByIdV2","tags":["Addresses"],"security":[{"oauth2":["identity.profiles.write"]}],"parameters":[{"$ref":"#/components/parameters/AddressIdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAddressRequest"}}}},"responses":{"200":{"description":"Address updated successfully.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressV2"}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}},"get":{"summary":"Get an address by ID","description":"Returns a single address by its ID, scoped to the authenticated customer.\n\nReturns 404 if the address does not exist or is not visible to the authenticated customer. A 403 is returned only when the caller's token lacks the required scope; cross-customer access returns 404, not 403.\n","operationId":"getAddressByIdV2","tags":["Addresses"],"security":[{"oauth2":["identity.profiles.read"]}],"parameters":[{"$ref":"#/components/parameters/AddressIdParam"}],"responses":{"200":{"description":"Address retrieved successfully.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressV2"}}}},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}}},"/v2/persons/{personId}/addresses":{"post":{"summary":"Create an address for a person","description":"Creates a new address and associates it with the specified person under the authenticated customer's scope.\n\nReturns 404 if the person does not exist or is not visible to the authenticated customer. A 403 is returned only when the caller's token lacks the required scope; cross-customer access returns 404, not 403. Returns 400 when the request body fails validation (V2 error shape).\n","operationId":"createPersonAddressV2","tags":["Addresses"],"security":[{"oauth2":["identity.profiles.write"]}],"parameters":[{"$ref":"#/components/parameters/PersonIdParam"},{"$ref":"#/components/parameters/IdempotencyKeyParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAddressRequest"}}}},"responses":{"201":{"description":"Address created successfully.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressV2"}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}},"get":{"summary":"List addresses for a person","description":"Returns addresses belonging to the specified person and visible to the authenticated customer, paginated by opaque continuation token. Results are ordered by (modifiedDate ASC, id ASC).\n\nReturns 404 if the person does not exist or is not visible to the authenticated customer. A 403 is returned only when the caller's token lacks the required scope; cross-customer access returns 404, not 403.\n","operationId":"listPersonAddressesV2","tags":["Addresses"],"security":[{"oauth2":["identity.profiles.read"]}],"parameters":[{"$ref":"#/components/parameters/PersonIdParam"},{"$ref":"#/components/parameters/PageToken"},{"$ref":"#/components/parameters/PageSize"}],"responses":{"200":{"description":"A page of addresses belonging to the person.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"type":"object","required":["items","page"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AddressV2"}},"page":{"$ref":"#/components/schemas/Page"}}}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}}},"/v2/firms/{firmId}/addresses":{"post":{"summary":"Create an address for a firm","description":"Creates a new address and associates it with the specified firm under the authenticated customer's scope.\n\nReturns 404 if the firm does not exist or is not visible to the authenticated customer. A 403 is returned only when the caller's token lacks the required scope; cross-customer access returns 404, not 403. Returns 400 when the request body fails validation (V2 error shape).\n","operationId":"createFirmAddressV2","tags":["Addresses"],"security":[{"oauth2":["identity.profiles.write"]}],"parameters":[{"$ref":"#/components/parameters/FirmIdParam"},{"$ref":"#/components/parameters/IdempotencyKeyParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAddressRequest"}}}},"responses":{"201":{"description":"Address created successfully.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressV2"}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}},"get":{"summary":"List addresses for a firm","description":"Returns addresses belonging to the specified firm and visible to the authenticated customer, paginated by opaque continuation token. Results are ordered by (modifiedDate ASC, id ASC).\n\nReturns 404 if the firm does not exist or is not visible to the authenticated customer. A 403 is returned only when the caller's token lacks the required scope; cross-customer access returns 404, not 403.\n","operationId":"listFirmAddressesV2","tags":["Addresses"],"security":[{"oauth2":["identity.profiles.read"]}],"parameters":[{"$ref":"#/components/parameters/FirmIdParam"},{"$ref":"#/components/parameters/PageToken"},{"$ref":"#/components/parameters/PageSize"}],"responses":{"200":{"description":"A page of addresses belonging to the firm.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"type":"object","required":["items","page"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AddressV2"}},"page":{"$ref":"#/components/schemas/Page"}}}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}}},"/v2/phones/{phoneId}":{"get":{"summary":"Retrieve a phone","description":"Returns a single phone by its identifier.\n\nA `404` is returned when the phone does not exist **or** is not visible to the authenticated customer — the two cases are intentionally indistinguishable so that resource existence is never leaked across customers. A `403` is returned only when the access token is missing the required scope.\n","operationId":"getPhoneV2","tags":["Phones"],"security":[{"oauth2":["identity.profiles.read"]}],"parameters":[{"name":"phoneId","in":"path","required":true,"description":"Phone identifier.","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}}],"responses":{"200":{"description":"The requested phone.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhoneV2"}}}},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}},"put":{"summary":"Update a phone","description":"Updates a single phone by its identifier, scoped to the authenticated customer. Setting `preferred: true` unprefers all other phones for the owning person.\n\nA `404` is returned when the phone does not exist **or** is not visible to the authenticated customer — the two cases are intentionally indistinguishable so that resource existence is never leaked across customers. A `403` is returned only when the access token is missing the required scope.\n","operationId":"updatePhoneV2","tags":["Phones"],"security":[{"oauth2":["identity.profiles.write"]}],"parameters":[{"name":"phoneId","in":"path","required":true,"description":"Phone identifier.","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePhoneRequest"}}}},"responses":{"200":{"description":"The updated phone.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhoneV2"}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}},"delete":{"summary":"Delete phone","description":"Permanently deletes a phone by ID, scoped to the authenticated customer. Returns 404 (never 403) when the phone does not exist or belongs to a different customer. The two cases are intentionally indistinguishable — the endpoint does not return an idempotent 204 for unknown IDs — so that resource existence is not leaked across customers.\n","operationId":"deletePhoneV2","tags":["Phones"],"security":[{"oauth2":["identity.profiles.write"]}],"parameters":[{"name":"phoneId","in":"path","required":true,"description":"Phone identifier.","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}}],"responses":{"204":{"description":"Phone deleted successfully.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}}},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}}},"/v2/persons/{personId}/phones":{"post":{"summary":"Create a phone for a person","description":"Creates a new phone and associates it with the specified person. The first phone added is automatically marked preferred. Sending preferred: true on a subsequent phone unprefers all existing phones for that person. A person may have at most 5 phones.\n","operationId":"createPersonPhoneV2","tags":["Phones"],"security":[{"oauth2":["identity.profiles.write"]}],"parameters":[{"$ref":"#/components/parameters/PersonIdParam"},{"$ref":"#/components/parameters/IdempotencyKeyParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePhoneRequest"}}}},"responses":{"201":{"description":"Phone created successfully.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhoneV2"}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}},"get":{"summary":"List phones for a person","description":"Returns phones belonging to the specified person and visible to the authenticated customer, paginated by continuation token.\n","operationId":"listPersonPhonesV2","tags":["Phones"],"security":[{"oauth2":["identity.profiles.read"]}],"parameters":[{"$ref":"#/components/parameters/PersonIdParam"},{"$ref":"#/components/parameters/PageToken"},{"$ref":"#/components/parameters/PageSize"}],"responses":{"200":{"description":"A page of phones belonging to the person.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"type":"object","required":["items","page"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PhoneV2"}},"page":{"$ref":"#/components/schemas/Page"}}}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}}},"/v2/firms/{firmId}/phones":{"post":{"summary":"Create a phone for a firm","description":"Creates a new phone and associates it with the specified firm. A firm may have at most 5 phones.\n","operationId":"createFirmPhoneV2","tags":["Phones"],"security":[{"oauth2":["identity.profiles.write"]}],"parameters":[{"$ref":"#/components/parameters/FirmIdParam"},{"$ref":"#/components/parameters/IdempotencyKeyParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePhoneRequest"}}}},"responses":{"201":{"description":"Phone created successfully.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhoneV2"}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}},"get":{"summary":"List phones for a firm","description":"Returns phones belonging to the specified firm and visible to the authenticated customer, paginated by continuation token.\n","operationId":"listFirmPhonesV2","tags":["Phones"],"security":[{"oauth2":["identity.profiles.read"]}],"parameters":[{"$ref":"#/components/parameters/FirmIdParam"},{"$ref":"#/components/parameters/PageToken"},{"$ref":"#/components/parameters/PageSize"}],"responses":{"200":{"description":"A page of phones belonging to the firm.","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"}},"content":{"application/json":{"schema":{"type":"object","required":["items","page"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PhoneV2"}},"page":{"$ref":"#/components/schemas/Page"}}}}}},"400":{"$ref":"#/components/responses/V2BadRequest"},"401":{"$ref":"#/components/responses/V2Unauthorized"},"403":{"$ref":"#/components/responses/V2Forbidden"},"404":{"$ref":"#/components/responses/V2NotFound"},"429":{"$ref":"#/components/responses/V2TooManyRequests"},"500":{"$ref":"#/components/responses/V2InternalServerError"}}}}},"components":{"securitySchemes":{"oauth2":{"type":"oauth2","description":"OAuth2 client credentials. The `tokenUrl` below is the SANDBOX token endpoint; for production use `https://auth.agentsync.io/oauth2/token`. OpenAPI 3.0 permits only one token URL per flow, so both cannot be expressed here — see the Authentication section for the full environment table.\n","flows":{"clientCredentials":{"tokenUrl":"https://auth.sandbox.agentsync.io/oauth2/token","scopes":{"identity.profiles.read":"Read access to producer profile resources (V2 customer-facing)","identity.profiles.write":"Write access to producer profile resources (V2 customer-facing)"}}}}},"parameters":{"BankAccountIdParam":{"name":"bankAccountId","in":"path","description":"The unique identifier for the bank account","required":true,"schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}},"PageToken":{"name":"page_token","in":"query","required":false,"description":"Opaque continuation token returned by the previous response's `page.nextToken`. Omit on the first request. Format is server-controlled and may change without an API version bump.\n","schema":{"type":"string"}},"PageSize":{"name":"page_size","in":"query","required":false,"description":"Requested number of items in the response. Defaults to 25 when omitted; values outside `[1, 250]` are rejected with `400` (not clamped). The actual size returned is reflected in `page.size` and may be smaller (last page or empty result).\n","schema":{"type":"integer","format":"int32","minimum":1,"maximum":250,"default":25}},"PersonIdParam":{"name":"personId","in":"path","description":"ID of the person","required":true,"schema":{"type":"string","format":"uuid"}},"FirmIdParam":{"name":"firmId","in":"path","description":"ID of the firm","required":true,"schema":{"type":"string","format":"uuid"}},"InsurancePolicyIdParam":{"name":"policyId","in":"path","description":"The unique identifier for the insurance policy.","required":true,"schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}},"IdempotencyKeyParam":{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Client-generated UUID used to deduplicate retried requests. When provided, the server caches the first successful response for this key and returns it for any subsequent request with the same key from the same client, without re-processing.\n"},"AddressIdParam":{"name":"addressId","in":"path","description":"ID of the address","required":true,"schema":{"type":"string","format":"uuid"}}},"headers":{"ratelimit-limit":{"description":"Maximum number of requests allowed per rate-limit window for the authenticated credential. The value returned in this header is authoritative; do not cache it.\n","schema":{"type":"integer"}},"ratelimit-remaining":{"description":"Number of requests remaining in the current rate-limit window.","schema":{"type":"integer"}},"ratelimit-reset":{"description":"Unix timestamp (seconds) after which at least one additional request slot becomes available. In a sliding window this is a hint, not a hard reset point — retrying exactly at this instant may still return 429 under sustained load.\n","schema":{"type":"integer"}},"Retry-After":{"description":"Minimum seconds to wait before retrying. Use this value directly as your retry delay; it already accounts for any server-side backoff.\n","schema":{"type":"integer"}}},"schemas":{"BankAccountType":{"title":"BankAccountType","type":"string","description":"The type of bank account","enum":["SAVINGS","CHECKING"],"example":"CHECKING"},"BankAccountFullResponse":{"title":"BankAccountFullResponse","description":"Bank account resource returned by the single-resource GET endpoint. The `number` field contains the full account number. In all other endpoints `number` is masked to `****<last4>`.\n","type":"object","required":["id","type","holderName","number","routingNumber","bankName","primaryAccount","createdAt"],"properties":{"id":{"type":"string","format":"uuid","description":"The unique identifier for the bank account.","readOnly":true,"example":"550e8400-e29b-41d4-a716-446655440000"},"type":{"$ref":"#/components/schemas/BankAccountType"},"holderName":{"type":"string","description":"Name of the account holder.","example":"Jane Doe"},"number":{"type":"string","description":"Full bank account number.","readOnly":true,"example":"1234567890"},"routingNumber":{"type":"string","description":"Bank routing number.","readOnly":true,"example":"021000021"},"bankName":{"type":"string","description":"Name of the bank.","example":"Chase Bank"},"nickname":{"type":"string","description":"Optional nickname for the bank account.","example":"Main"},"primaryAccount":{"type":"boolean","description":"Indicates if this is the primary bank account.","example":true},"createdAt":{"type":"string","format":"date-time","description":"RFC3339 UTC timestamp when the bank account was created.","readOnly":true,"example":"2024-01-15T10:30:00Z"},"updatedAt":{"type":"string","format":"date-time","description":"RFC3339 UTC timestamp when the bank account was last updated.","readOnly":true,"nullable":true,"example":"2024-01-15T14:45:00Z"}}},"V2FieldError":{"type":"object","required":["param","message"],"properties":{"param":{"type":"string","description":"The request field that failed validation","example":"email"},"message":{"type":"string","description":"Human-readable description of the failure","example":"must not be blank"}}},"V2Error":{"type":"object","required":["message","details","code"],"properties":{"message":{"type":"string","description":"Human-readable error summary. Do not parse — use \"code\" for branching.","example":"Validation failed"},"details":{"type":"array","description":"Per-field validation errors. Empty for all non-400 responses.","items":{"$ref":"#/components/schemas/V2FieldError"}},"code":{"type":"string","description":"Stable machine-readable error code.","enum":["validation_failed","unauthorized","unauthorized_scope","resource_not_found","conflict","unprocessable","unsupported_media_type","rate_limited","internal"],"example":"validation_failed"}}},"UpdateBankAccountRequest":{"title":"UpdateBankAccountRequest","type":"object","required":["type","holderName","number","routingNumber","bankName"],"properties":{"type":{"$ref":"#/components/schemas/BankAccountType"},"holderName":{"type":"string","description":"Name of the account holder","example":"Jane Doe"},"number":{"type":"string","description":"Bank account number (4-17 digits)","minLength":4,"maxLength":17,"pattern":"^\\d{4,17}$","example":"9876543210"},"routingNumber":{"type":"string","description":"Bank routing number (exactly 9 digits)","minLength":9,"maxLength":9,"pattern":"^\\d{9}$","example":"021000021"},"bankName":{"type":"string","description":"Name of the bank","example":"Wells Fargo"},"nickname":{"type":"string","description":"Optional nickname for the bank account","example":"Secondary"},"primaryAccount":{"type":"boolean","nullable":true,"description":"Whether this should become the owner's primary bank account. Setting `true` demotes any existing primary for the same owner. An existing primary account cannot be demoted directly by omitting or setting this to `false` — set another account as primary instead. `null` is treated the same as omitted.\n","default":false,"example":false}}},"BankAccountResponse":{"title":"BankAccountResponse","type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The unique identifier for the bank account","readOnly":true,"example":"550e8400-e29b-41d4-a716-446655440000"},"type":{"$ref":"#/components/schemas/BankAccountType"},"holderName":{"type":"string","description":"Name of the account holder","example":"Jane Doe"},"number":{"type":"string","description":"Masked bank account number (last 4 digits visible)","readOnly":true,"example":"****7890"},"routingNumber":{"type":"string","description":"Bank routing number","readOnly":true,"example":"021000021"},"bankName":{"type":"string","description":"Name of the bank","example":"Chase Bank"},"nickname":{"type":"string","description":"Optional nickname for the bank account","example":"Main"},"primaryAccount":{"type":"boolean","description":"Indicates if this is the primary bank account","example":true},"createdAt":{"type":"string","format":"date-time","description":"Timestamp when the bank account was created","readOnly":true,"example":"2024-01-15T10:30:00Z"},"updatedAt":{"type":"string","format":"date-time","description":"Timestamp when the bank account was last updated","readOnly":true,"nullable":true,"example":"2024-01-15T14:45:00Z"}}},"BankAccountListItemV2":{"title":"BankAccountListItemV2","type":"object","description":"Per-row shape returned by V2 bank-account list endpoints. Carries owner context (personId or firmId, plus the producer NPN where known) for reconciliation use cases. The account number is always masked here; the unmasked value is reachable only via GET /v2/bank-accounts/{id} behind an elevated scope.\n","required":["id","type","bankName","number","primaryAccount","updatedAt"],"properties":{"id":{"type":"string","format":"uuid","description":"Bank account identifier.","example":"550e8400-e29b-41d4-a716-446655440000"},"personId":{"type":"string","format":"uuid","nullable":true,"description":"Owning person id. Set when this is a person-owned bank account; null for firm-owned."},"firmId":{"type":"string","format":"uuid","nullable":true,"description":"Owning firm id. Set when this is a firm-owned bank account; null for person-owned."},"npn":{"type":"string","nullable":true,"description":"National Producer Number of the owning person or firm, when known.","example":"1234567"},"type":{"$ref":"#/components/schemas/BankAccountType"},"bankName":{"type":"string","description":"Name of the bank.","example":"Chase Bank"},"number":{"type":"string","description":"Account number masked to ****<last4>.","example":"****7890"},"primaryAccount":{"type":"boolean","description":"Indicates if this is the owner's primary bank account.","example":true},"updatedAt":{"type":"string","format":"date-time","description":"RFC3339 UTC timestamp of the bank account's last modification.","example":"2026-05-21T14:00:00Z"}}},"Page":{"type":"object","description":"Page metadata for a token-based list response.","required":["size","nextToken"],"properties":{"size":{"type":"integer","format":"int32","minimum":0,"description":"Number of items actually returned in this response — equal to `items.length`. On an empty result this is `0`. This is NOT a copy of the request's `page_size` hint; clients holding the hint already know what they asked for.\n","example":25},"nextToken":{"type":"string","nullable":true,"description":"Opaque token to request the next page. `null` when this is the last page. Pass back as the `page_token` query parameter to resume.\n","example":"eyJ2IjoxLCJrIjp7InVwZGF0ZWRBdCI6IjIwMjYtMDUtMTlUMTI6MDA6MDBaIiwiaWQiOiIwMUhYWVoifX0"}}},"CreateBankAccountRequest":{"title":"CreateBankAccountRequest","type":"object","required":["type","holderName","number","routingNumber","bankName"],"properties":{"type":{"$ref":"#/components/schemas/BankAccountType"},"holderName":{"type":"string","description":"Name of the account holder","example":"Jane Doe"},"number":{"type":"string","description":"Bank account number (4-17 characters)","minLength":4,"maxLength":17,"example":"1234567890"},"routingNumber":{"type":"string","description":"Bank routing number (exactly 9 digits)","minLength":9,"maxLength":9,"example":"021000021"},"bankName":{"type":"string","description":"Name of the bank","example":"Chase Bank"},"nickname":{"type":"string","description":"Optional nickname for the bank account","example":"Main"},"primaryAccount":{"type":"boolean","nullable":true,"description":"Whether this should become the owner's primary bank account. Setting `true` demotes any existing primary for the same owner. Defaults to `false` (the owner's first bank account always becomes primary regardless of this value). `null` is treated the same as omitted.\n","default":false,"example":false}}},"PolicyType":{"title":"PolicyType","type":"string","description":"The type of insurance policy","enum":["CORPORATION","INDIVIDUAL","JOINT"],"example":"INDIVIDUAL"},"InsurancePolicyV2":{"type":"object","required":["id","type","carrier","effectiveOn","policyNumber","certificateNumber","createdAt","updatedAt"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for the insurance policy.","readOnly":true},"type":{"$ref":"#/components/schemas/PolicyType"},"carrier":{"type":"string","description":"Name of the insurance carrier."},"totalLimit":{"type":"number","format":"double","description":"Maximum coverage limit for the policy."},"effectiveOn":{"type":"string","format":"date","description":"Date the insurance policy became effective (YYYY-MM-DD)."},"expiresOn":{"type":"string","format":"date","description":"Date the insurance policy expires (YYYY-MM-DD)."},"policyNumber":{"type":"string","description":"Policy number assigned by the carrier."},"certificateNumber":{"type":"string","description":"Certificate number for the policy."},"hasFile":{"type":"boolean","description":"Whether a certificate file has been uploaded for this policy.","readOnly":true},"certificateUrl":{"type":"string","format":"uri","description":"Presigned download URL for the certificate file. Present only when hasFile is true. Expires 10 minutes after the response is generated.","readOnly":true,"nullable":true},"createdAt":{"type":"string","format":"date-time","description":"RFC3339 UTC timestamp when the record was created.","readOnly":true},"updatedAt":{"type":"string","format":"date-time","description":"RFC3339 UTC timestamp when the record was last updated.","readOnly":true}}},"UpdateInsurancePolicyRequest":{"type":"object","required":["type","carrier","effectiveOn","policyNumber","certificateNumber"],"properties":{"type":{"$ref":"#/components/schemas/PolicyType"},"carrier":{"type":"string","description":"Name of the insurance carrier.","example":"Acme Insurance Co."},"totalLimit":{"type":"number","format":"double","description":"Maximum coverage limit for the policy.","minimum":1,"maximum":10000000,"example":1000000},"effectiveOn":{"type":"string","format":"date","description":"Date the insurance policy becomes effective (YYYY-MM-DD).","example":"2024-01-01"},"expiresOn":{"type":"string","format":"date","description":"Date the insurance policy expires (YYYY-MM-DD).","example":"2025-01-01"},"policyNumber":{"type":"string","description":"Policy number assigned by the carrier.","example":"POL-001"},"certificateNumber":{"type":"string","description":"Certificate number for the policy.","example":"CERT-001"}}},"CreateInsurancePolicyRequest":{"type":"object","required":["type","carrier","effectiveOn","policyNumber","certificateNumber"],"properties":{"type":{"$ref":"#/components/schemas/PolicyType"},"carrier":{"type":"string","description":"Name of the insurance carrier.","example":"Acme Insurance Co."},"totalLimit":{"type":"number","format":"double","description":"Maximum coverage limit for the policy.","minimum":1,"maximum":10000000,"example":1000000},"effectiveOn":{"type":"string","format":"date","description":"Date the insurance policy becomes effective (YYYY-MM-DD).","example":"2024-01-01"},"expiresOn":{"type":"string","format":"date","description":"Date the insurance policy expires (YYYY-MM-DD).","example":"2025-01-01"},"policyNumber":{"type":"string","description":"Policy number assigned by the carrier.","example":"POL-001"},"certificateNumber":{"type":"string","description":"Certificate number for the policy.","example":"CERT-001"}}},"FirmV2":{"title":"FirmV2","description":"Customer-facing firm resource. The FEIN is always masked to ****<last4>; the full FEIN is available only via GET /v2/firms/{firmId}/fein (audited).\n","type":"object","required":["id","npn","createdAt"],"properties":{"id":{"type":"string","format":"uuid","description":"The unique identifier of the firm.","readOnly":true,"example":"550e8400-e29b-41d4-a716-446655440000"},"npn":{"type":"string","description":"National Producer Number.","readOnly":true,"example":"1234567"},"name":{"type":"string","description":"Legal name of the firm.","example":"Acme Insurance LLC"},"email":{"type":"string","format":"email","description":"Primary contact email address.","example":"contact@acme.com"},"type":{"type":"string","description":"Business entity type (SC, LLC, SP).","example":"LLC"},"finraCrdNumber":{"type":"string","description":"FINRA CRD number (digits only, max 11 characters).","example":"12345"},"fein":{"type":"string","description":"Masked Federal Employer Identification Number. Always returned as ****<last4>. The full FEIN is never exposed by this endpoint.\n","readOnly":true,"example":"****6789"},"testAccount":{"type":"boolean","description":"Whether this is a test account.","example":false},"createdAt":{"type":"string","format":"date-time","description":"ISO-8601 UTC timestamp when the firm was created.","readOnly":true,"example":"2024-01-15T10:30:00Z"},"updatedAt":{"type":"string","format":"date-time","description":"ISO-8601 UTC timestamp of the last update.","readOnly":true,"example":"2024-06-01T14:22:00Z"}}},"FirmV2List":{"title":"FirmV2List","description":"Keyset-paginated list of firms (F5 envelope).","type":"object","required":["items","page"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/FirmV2"}},"page":{"$ref":"#/components/schemas/Page"}}},"UpdateFirmRequest":{"title":"UpdateFirmRequest","description":"Fields that may be updated on a firm. All fields are optional — omitted fields leave the stored value unchanged. The `npn` and `fein` fields are immutable and cannot be set via this endpoint.\n","type":"object","properties":{"name":{"type":"string","description":"Legal name of the firm.","example":"Acme Insurance LLC"},"email":{"type":"string","format":"email","description":"Primary contact email address.","example":"contact@acme.com"},"type":{"type":"string","description":"Business entity type (SC, LLC, SP).","example":"LLC"},"finraCrdNumber":{"type":"string","description":"FINRA CRD number (digits only, max 11 characters).","pattern":"^[0-9]*$","maxLength":11,"example":"12345"}}},"FeinDto":{"title":"FeinDto","description":"Carries a firm's full, unmasked Federal Employer Identification Number. Returned only by GET /v2/firms/{firmId}/fein; the FEIN is masked in all other responses.\n","type":"object","required":["firmId","fein"],"properties":{"firmId":{"type":"string","format":"uuid","description":"The unique identifier of the firm.","example":"550e8400-e29b-41d4-a716-446655440000"},"fein":{"type":"string","description":"The full, unmasked Federal Employer Identification Number (9 digits).","example":"123456789"}}},"PersonTitle":{"type":"string","nullable":true,"enum":["DR","MR","MRS","MS","MISS"],"description":"The person's honorific title.","example":"MS"},"PersonSuffix":{"type":"string","nullable":true,"enum":["JR","SR","I","II","III","OBE","MBE","BSC","JP","GM"],"description":"The person's name suffix.","example":"JR"},"PersonGender":{"type":"string","nullable":true,"enum":["MALE","FEMALE"],"description":"The person's gender.","example":"FEMALE"},"PersonListItemV2":{"title":"PersonListItemV2","description":"A single person row returned by GET /v2/persons. Carries the person's core identity fields. Related resources such as addresses, phones, employments, and licenses are not included here — retrieve them via the single-resource and dedicated collection endpoints.\n","type":"object","required":["id","updatedAt","createdAt"],"properties":{"id":{"type":"string","format":"uuid","description":"The unique identifier of the person.","readOnly":true,"example":"550e8400-e29b-41d4-a716-446655440000"},"firstName":{"type":"string","description":"The person's first name.","example":"Jane"},"middleName":{"type":"string","nullable":true,"description":"The person's middle name.","example":"Quincy"},"lastName":{"type":"string","description":"The person's last name.","example":"Smith"},"preferredFirstName":{"type":"string","nullable":true,"description":"The name the person prefers to be addressed by, when different from their legal first name.","example":"Janey"},"title":{"$ref":"#/components/schemas/PersonTitle"},"suffix":{"$ref":"#/components/schemas/PersonSuffix"},"primaryEmail":{"type":"string","format":"email","description":"The person's primary contact email address.","example":"jane.smith@example.com"},"secondaryEmail":{"type":"string","format":"email","nullable":true,"description":"The person's secondary contact email address.","example":"jane.alt@example.com"},"dateOfBirth":{"type":"string","format":"date","nullable":true,"description":"The person's date of birth (YYYY-MM-DD).","example":"1990-05-15"},"gender":{"$ref":"#/components/schemas/PersonGender"},"citizenshipCountry":{"type":"string","nullable":true,"description":"The person's country of citizenship.","example":"US"},"residentState":{"type":"string","nullable":true,"description":"The person's state of residence.","example":"CO"},"unitedStatesCitizen":{"type":"boolean","nullable":true,"description":"Whether the person is a United States citizen.","example":true},"unitedStatesWorkAuthorized":{"type":"boolean","nullable":true,"description":"Whether the person is authorized to work in the United States.","example":true},"married":{"type":"boolean","nullable":true,"description":"Whether the person is married.","example":false},"npn":{"type":"string","nullable":true,"description":"National Producer Number. Null when the person's NPN has not been verified.","example":"12345678"},"finraCrdNumber":{"type":"string","nullable":true,"description":"The person's FINRA Central Registration Depository (CRD) number.","example":"1234567"},"ssnLast4":{"type":"string","nullable":true,"description":"Last four digits of the Social Security Number. Null when no SSN is on record.","example":"6789"},"createdAt":{"type":"string","format":"date-time","description":"RFC3339 timestamp when the person record was created.","readOnly":true,"example":"2026-01-15T10:30:00Z"},"updatedAt":{"type":"string","format":"date-time","description":"RFC3339 timestamp of the most recent modification. Use this field with updated_since for delta sync.","readOnly":true,"example":"2026-06-01T14:22:00Z"}}},"CreatePersonRequest":{"title":"CreatePersonRequest","description":"Fields for creating a new person. `firstName`, `lastName`, and `primaryEmail` are required. `sendInvite` defaults to `false`; set it to `true` to trigger an email invitation. Internal-only fields (customer ID, intake ID) are not accepted.\n","type":"object","required":["firstName","lastName","primaryEmail"],"properties":{"firstName":{"type":"string","example":"Jane"},"lastName":{"type":"string","example":"Smith"},"middleName":{"type":"string","nullable":true},"preferredFirstName":{"type":"string","nullable":true,"maxLength":100},"title":{"$ref":"#/components/schemas/PersonTitle"},"suffix":{"$ref":"#/components/schemas/PersonSuffix"},"dateOfBirth":{"type":"string","format":"date","nullable":true},"gender":{"$ref":"#/components/schemas/PersonGender"},"primaryEmail":{"type":"string","format":"email","example":"jane.smith@example.com"},"secondaryEmail":{"type":"string","format":"email","nullable":true},"citizenshipCountry":{"type":"string","nullable":true},"residentState":{"type":"string","nullable":true},"unitedStatesCitizen":{"type":"boolean","nullable":true},"unitedStatesWorkAuthorized":{"type":"boolean","nullable":true},"married":{"type":"boolean","nullable":true},"npn":{"type":"string","nullable":true,"maxLength":12,"pattern":"^[1-9][0-9]*$","description":"National Producer Number. Must start with a non-zero digit and contain only digits."},"finraCrdNumber":{"type":"string","nullable":true,"maxLength":11,"pattern":"^[0-9]+$","description":"FINRA CRD number. Must contain only digits."},"ssn":{"type":"string","nullable":true,"minLength":9,"maxLength":9,"pattern":"^[0-9]*$","description":"Social Security Number. Must be exactly 9 digits."},"sendInvite":{"type":"boolean","default":false,"description":"When true, sends an email invitation to the person. Defaults to false."}}},"PersonV2":{"title":"PersonV2","description":"Customer-facing producer identity. SSN is masked — only the last four digits are present via `ssnLast4`. The full unmasked SSN is available only via `GET /v2/persons/{personId}/ssn`.\n","type":"object","required":["id","npnVerified","createdAt","updatedAt"],"properties":{"id":{"type":"string","format":"uuid","description":"The unique identifier of the person.","readOnly":true,"example":"550e8400-e29b-41d4-a716-446655440000"},"title":{"$ref":"#/components/schemas/PersonTitle"},"firstName":{"type":"string","description":"The person's first name.","example":"Jane"},"preferredFirstName":{"type":"string","nullable":true,"description":"The name the person prefers to be addressed by, when different from their legal first name.","example":"Janey"},"middleName":{"type":"string","nullable":true,"description":"The person's middle name.","example":"Quincy"},"lastName":{"type":"string","description":"The person's last name.","example":"Smith"},"suffix":{"$ref":"#/components/schemas/PersonSuffix"},"primaryEmail":{"type":"string","format":"email","nullable":true,"description":"The person's primary contact email address.","example":"jane.smith@example.com"},"secondaryEmail":{"type":"string","format":"email","nullable":true,"description":"The person's secondary contact email address.","example":"jane.alt@example.com"},"dateOfBirth":{"type":"string","format":"date","nullable":true,"description":"The person's date of birth (YYYY-MM-DD).","example":"1990-05-15"},"gender":{"$ref":"#/components/schemas/PersonGender"},"citizenshipCountry":{"type":"string","nullable":true,"description":"The person's country of citizenship.","example":"US"},"residentState":{"type":"string","nullable":true,"description":"The person's state of residence.","example":"CO"},"unitedStatesCitizen":{"type":"boolean","nullable":true,"description":"Whether the person is a United States citizen.","example":true},"unitedStatesWorkAuthorized":{"type":"boolean","nullable":true,"description":"Whether the person is authorized to work in the United States.","example":true},"married":{"type":"boolean","nullable":true,"description":"Whether the person is married.","example":false},"npn":{"type":"string","nullable":true,"description":"National Producer Number.","example":"12345678"},"npnVerified":{"type":"boolean","readOnly":true,"description":"Whether the person's NPN has been verified against NIPR."},"finraCrdNumber":{"type":"string","nullable":true,"description":"The person's FINRA Central Registration Depository (CRD) number.","example":"1234567"},"ssnLast4":{"type":"string","nullable":true,"description":"Last four digits of the Social Security Number. Full SSN available only via GET /v2/persons/{personId}/ssn.","example":"6789"},"createdAt":{"type":"string","format":"date-time","description":"RFC3339 timestamp when the person record was created.","readOnly":true,"example":"2026-01-15T10:30:00Z"},"updatedAt":{"type":"string","format":"date-time","description":"RFC3339 timestamp of the most recent modification.","readOnly":true,"example":"2026-06-01T14:22:00Z"}}},"UpdatePersonRequest":{"title":"UpdatePersonRequest","description":"Fields to apply to a person. Only non-null fields are applied — omitted or null fields leave the stored value untouched (partial update). `firstName` and `lastName` are required.\n","type":"object","required":["firstName","lastName"],"properties":{"firstName":{"type":"string","example":"Grace"},"lastName":{"type":"string","example":"Hopper"},"middleName":{"type":"string","nullable":true},"preferredFirstName":{"type":"string","nullable":true,"maxLength":100},"title":{"$ref":"#/components/schemas/PersonTitle"},"suffix":{"$ref":"#/components/schemas/PersonSuffix"},"dateOfBirth":{"type":"string","format":"date","nullable":true},"gender":{"$ref":"#/components/schemas/PersonGender"},"primaryEmail":{"type":"string","format":"email","nullable":true},"secondaryEmail":{"type":"string","format":"email","nullable":true},"citizenshipCountry":{"type":"string","nullable":true},"residentState":{"type":"string","nullable":true},"unitedStatesCitizen":{"type":"boolean","nullable":true},"unitedStatesWorkAuthorized":{"type":"boolean","nullable":true},"married":{"type":"boolean","nullable":true},"npn":{"type":"string","nullable":true,"maxLength":12,"pattern":"^[1-9][0-9]*$","description":"National Producer Number. Must start with a non-zero digit and contain only digits."},"finraCrdNumber":{"type":"string","nullable":true,"maxLength":11,"pattern":"^[0-9]+$","description":"FINRA CRD number. Must contain only digits."},"ssn":{"type":"string","nullable":true,"minLength":9,"maxLength":9,"pattern":"^[0-9]*$","description":"Social Security Number. Must be exactly 9 digits."}}},"SsnResponse":{"title":"SsnResponse","description":"Carries a person's full, unmasked Social Security Number. Returned only by GET /v2/persons/{personId}/ssn; the SSN is masked in all other responses.\n","type":"object","required":["personId","ssn"],"properties":{"personId":{"type":"string","format":"uuid","description":"The unique identifier of the person.","readOnly":true,"example":"550e8400-e29b-41d4-a716-446655440000"},"ssn":{"type":"string","description":"The full, unmasked Social Security Number (9 digits).","readOnly":true,"example":"123456789"}}},"AssociateFirmRequestV2":{"title":"AssociateFirmRequestV2","description":"Identifies the existing firm to associate with the person, and optionally the person's role in it.","type":"object","required":["firmId"],"properties":{"firmId":{"type":"string","format":"uuid","description":"The unique identifier of the firm to associate.","example":"550e8400-e29b-41d4-a716-446655440000"},"role":{"type":"string","enum":["PRINCIPAL","AGENT_FIRM_MANAGER","AGENT"],"default":"PRINCIPAL","description":"The person's role in the firm. Defaults to PRINCIPAL when omitted.","example":"PRINCIPAL"}}},"PersonFirmV2":{"title":"PersonFirmV2","description":"An association between a person and a firm.","type":"object","required":["personId","firmId","role"],"properties":{"personId":{"type":"string","format":"uuid","description":"The unique identifier of the associated person.","readOnly":true,"example":"550e8400-e29b-41d4-a716-446655440000"},"firmId":{"type":"string","format":"uuid","description":"The unique identifier of the associated firm.","readOnly":true,"example":"660e8400-e29b-41d4-a716-446655440111"},"role":{"type":"string","enum":["PRINCIPAL","AGENT_FIRM_MANAGER","AGENT"],"description":"The person's role in the firm.","example":"PRINCIPAL"}}},"AddressType":{"type":"string","enum":["MAILING","BUSINESS","PHYSICAL"],"description":"Type of address"},"AddressV2":{"title":"AddressV2","type":"object","required":["id","type","addressLine1","city","state","zip","country","preferred","createdAt"],"properties":{"id":{"type":"string","format":"uuid","description":"Address identifier.","readOnly":true,"example":"550e8400-e29b-41d4-a716-446655440000"},"type":{"$ref":"#/components/schemas/AddressType"},"addressLine1":{"type":"string","description":"First line of the street address.","example":"123 Main St"},"addressLine2":{"type":"string","nullable":true,"description":"Second line of the street address (suite, unit, etc.).","example":"Apt 4B"},"city":{"type":"string","description":"City.","example":"Denver"},"state":{"type":"string","minLength":2,"maxLength":2,"description":"Two-letter US state code.","example":"CO"},"zip":{"type":"string","nullable":true,"pattern":"^\\d{5}(-\\d{4})?$","description":"ZIP code in 5-digit or ZIP+4 format.","example":"80202"},"county":{"type":"string","nullable":true,"description":"County name.","example":"Denver"},"country":{"type":"string","nullable":true,"minLength":2,"maxLength":2,"description":"Country code (ISO alpha-2).","example":"US"},"moveInDate":{"type":"string","format":"date","nullable":true,"description":"Date the person moved to this address (YYYY-MM-DD).","example":"2020-01-15"},"preferred":{"type":"boolean","description":"Whether this is the person's preferred address.","example":true},"createdAt":{"type":"string","format":"date-time","description":"RFC3339 UTC timestamp when the address was created.","readOnly":true,"example":"2024-01-15T10:30:00Z"},"updatedAt":{"type":"string","format":"date-time","nullable":true,"description":"RFC3339 UTC timestamp when the address was last updated.","readOnly":true,"example":"2024-01-15T14:45:00Z"}}},"UpdateAddressRequest":{"title":"UpdateAddressRequest","type":"object","required":["type","addressLine1","city","state","zip","country"],"properties":{"type":{"$ref":"#/components/schemas/AddressType"},"addressLine1":{"type":"string","description":"First line of the street address.","example":"123 Main St"},"addressLine2":{"type":"string","nullable":true,"description":"Second line of the street address (suite, unit, etc.).","example":"Apt 4B"},"city":{"type":"string","description":"City.","example":"Denver"},"state":{"type":"string","description":"Two-letter US state code.","example":"CO"},"zip":{"type":"string","pattern":"^\\d{5}(-\\d{4})?$","description":"ZIP code in 5-digit or ZIP+4 format.","example":"80202"},"county":{"type":"string","nullable":true,"description":"County name.","example":"Denver"},"country":{"type":"string","description":"Country code (ISO alpha-2).","example":"US"},"moveInDate":{"type":"string","format":"date","nullable":true,"description":"Date the person moved to this address (YYYY-MM-DD).","example":"2020-01-15"},"preferred":{"type":"boolean","nullable":true,"default":false,"description":"Whether this should be the preferred address. When true, any other preferred address for the same person or firm is automatically unset. Omitting or null is treated as false.\n","example":false}}},"CreateAddressRequest":{"title":"CreateAddressRequest","type":"object","required":["type","addressLine1","city","state","zip","country"],"properties":{"type":{"$ref":"#/components/schemas/AddressType"},"addressLine1":{"type":"string","description":"First line of the street address.","example":"123 Main St"},"addressLine2":{"type":"string","nullable":true,"description":"Second line of the street address (suite, unit, etc.).","example":"Apt 4B"},"city":{"type":"string","description":"City.","example":"Denver"},"state":{"type":"string","minLength":2,"maxLength":2,"description":"Two-letter US state code.","example":"CO"},"zip":{"type":"string","pattern":"^\\d{5}(-\\d{4})?$","description":"ZIP code in 5-digit or ZIP+4 format.","example":"80202"},"county":{"type":"string","nullable":true,"description":"County name.","example":"Denver"},"country":{"type":"string","minLength":2,"maxLength":2,"description":"Country code (ISO alpha-2).","example":"US"},"moveInDate":{"type":"string","format":"date","nullable":true,"description":"Date the person moved to this address (YYYY-MM-DD).","example":"2020-01-15"},"preferred":{"type":"boolean","default":false,"description":"Whether this should be the person's preferred address. When the person has no existing addresses, the server sets this to true regardless of the supplied value.\n","example":false}}},"PhoneType":{"title":"PhoneType","type":"string","description":"The type of phone","enum":["CELL","BUSINESS","RESIDENT","FAX"],"example":"CELL"},"PhoneV2":{"title":"PhoneV2","type":"object","description":"A phone record returned by V2 phone endpoints.\n","required":["id","type","number","preferred","createdAt"],"properties":{"id":{"type":"string","format":"uuid","description":"Phone identifier.","readOnly":true,"example":"550e8400-e29b-41d4-a716-446655440000"},"type":{"$ref":"#/components/schemas/PhoneType"},"number":{"type":"string","description":"10-digit phone number.","example":"3035551234"},"extension":{"type":"string","nullable":true,"description":"Optional phone extension.","example":"1234"},"preferred":{"type":"boolean","description":"Whether this is the preferred phone number.","example":true},"createdAt":{"type":"string","format":"date-time","description":"RFC3339 UTC timestamp when the phone was created.","readOnly":true,"example":"2024-01-15T10:30:00Z"},"updatedAt":{"type":"string","format":"date-time","nullable":true,"description":"RFC3339 UTC timestamp when the phone was last updated.","readOnly":true,"example":"2024-01-15T14:45:00Z"}}},"UpdatePhoneRequest":{"title":"UpdatePhoneRequest","type":"object","required":["type","number","preferred"],"properties":{"type":{"$ref":"#/components/schemas/PhoneType"},"number":{"type":"string","description":"Phone number (exactly 10 digits)","pattern":"^[0-9]{10}$","example":"3035551234"},"extension":{"type":"string","description":"Optional phone extension (max 6 characters)","maxLength":6,"example":"1234"},"preferred":{"type":"boolean","description":"Whether this is the preferred phone number","example":true}}},"CreatePhoneRequest":{"title":"CreatePhoneRequest","type":"object","required":["type","number","preferred"],"properties":{"type":{"$ref":"#/components/schemas/PhoneType"},"number":{"type":"string","description":"Phone number (exactly 10 digits)","pattern":"^[0-9]{10}$","example":"3035551234"},"extension":{"type":"string","description":"Optional phone extension (max 6 characters)","maxLength":6,"example":"1234"},"preferred":{"type":"boolean","description":"Whether this is the preferred phone number","example":true}}}},"responses":{"V2BadRequest":{"description":"One or more request fields failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V2Error"},"example":{"message":"Validation failed","code":"validation_failed","details":[{"param":"email","message":"must not be blank"}]}}}},"V2Unauthorized":{"description":"No valid bearer token was presented","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V2Error"},"example":{"message":"Authentication required","code":"unauthorized","details":[]}}}},"V2Forbidden":{"description":"The token does not carry the required scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V2Error"},"example":{"message":"Insufficient scope","code":"unauthorized_scope","details":[]}}}},"V2NotFound":{"description":"The requested resource does not exist or is not visible to the caller","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V2Error"},"example":{"message":"Resource not found","code":"resource_not_found","details":[]}}}},"V2TooManyRequests":{"description":"Rate limit exceeded. The caller has exceeded the maximum number of requests allowed per rate-limit window for the authenticated credential.\nNOTE: The response body for this status deviates from the standard V2 error shape ({message, details, code}). The body contains only a top-level \"message\" string. Clients should treat the Retry-After header as the authoritative retry signal and must not parse the message string.\n","headers":{"ratelimit-limit":{"$ref":"#/components/headers/ratelimit-limit"},"ratelimit-remaining":{"$ref":"#/components/headers/ratelimit-remaining"},"ratelimit-reset":{"$ref":"#/components/headers/ratelimit-reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string"}}},"example":{"message":"API rate limit exceeded"}}}},"V2InternalServerError":{"description":"An unexpected server error occurred","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V2Error"},"example":{"message":"An unexpected error occurred","code":"internal","details":[]}}}},"V2UnsupportedMediaType":{"description":"Content-Type is not application/json","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V2Error"},"example":{"message":"Unsupported media type","code":"unsupported_media_type","details":[]}}}}}}}
````
