# Seedly CRM 5.10.0 core OpenAPI snapshot
# Source commit: d1faf80417c1108954ba5cc20644db02bd602736
# Source SHA-256: c1beafe39578f103d8a1c3f09f08ebf5206a04df9f03a76c85524f046b89ac70
# Prose dashes normalized; use your installation export for enabled routes.
openapi: "3.1.0"
info:
  title: Seedly CRM API
  version: "1.0.0"
  description: |
    REST API for third-party integrations with Seedly CRM. Supports contacts, conversations,
    calendars, and webhook subscription management.

    ## Authentication

    Endpoints require a Bearer token in the `Authorization` header:

    ```
    Authorization: Bearer sk_live_...
    ```

    API keys carry a persisted permission model. Existing and unversioned keys use Legacy v1
    with unchanged scope semantics. Standard v2 keys are available for new location integrations,
    with separate delete and message-send permissions and an explicit route allowlist.
    Scope requirements below describe Legacy v1 unless marked for OAuth; for Standard v2,
    use the generated x-seedly-standard-scope and x-seedly-resource-restrictions metadata.
    OAuth and Standard v2 are projections of packages/shared/src/integration-capabilities.json.
    Agency keys and extension routes remain Legacy v1. No automatic migration or key rotation occurs.

    API keys are scoped to a single sub-account and carry specific permission scopes.
    Use `sk_test_` prefix keys for sandbox mode (messages recorded but not sent to providers).

    Agency-scoped keys (`sk_agency_live_*` / `sk_agency_test_*`) operate across all sub-accounts
    under an agency. These keys require the `X-Sub-Account-Id` header on every request to specify
    which sub-account to operate on. Use `GET /api/v1/sub-accounts` to discover available sub-accounts.

    Connected applications can use opaque OAuth access tokens on explicitly supported
    routes. Each grant is pinned to one location; location override headers are rejected.
    OAuth test mode simulates SMS/email delivery, but it is not a general sandbox:
    other authorized writes and configured workflow or billing effects can still occur.
    On Standard v2 and OAuth, a test credential is refused with 400 on an operation that
    would really send and has no simulation: campaign, invoice, estimate and document sends,
    invoice void, document reminders, review requests, public review replies, task submission
    approve and reject, form submission release, member invitations, social post publish,
    retry, schedule and approval, and any create, change, resume or generate of a recurring
    invoice that auto-sends.
    See `docs/integrations/connected-apps-contract.md` for the connection contract,
    issuer flow, per-app setup export and extension policy. Operations marked
    `x-seedly-oauth-scope` are in the base product's OAuth allowlist; this is not
    a grant. The installation may disable scopes and each app/location must be
    authorized separately. Unmarked operations are not base-product OAuth APIs.

    ## Request validation and compatibility

    Standard v2 and OAuth CRM JSON writes require a JSON object and application/json.
    Malformed JSON returns 400; unsupported MIME types return 415; actual body bytes
    exceeding the endpoint limit return 413. Legacy API keys and CloseBot retain
    their existing parser behavior. New-model list limits must be integers 1-100.

    ## Rate Limits

    Core resource budgets are per credential and resource: live read/write limits
    are 120/30 per minute; test limits are 30/10. Failed authentication is limited
    to 60 per minute per client address and does not affect valid credentials on that
    address. Each Standard v2 key and OAuth grant also has a ceiling across all routes
    of 1200 requests per minute (300 for test credentials). Legacy API keys and CloseBot
    keys have no ceiling across resources: valid requests are governed by the resource
    budgets, per location for a legacy agency key. Their location and HIPAA refusals spend
    a separate budget of 1200 per minute (300 for test keys) per key, which valid requests
    never spend or see. Failed authentication
    is also limited to 6000 per minute across the deployment, which valid credentials
    never spend or see. Operation work budgets also apply. Read the returned X-RateLimit headers. A 429 includes
    Retry-After. Error headers may be absent when no resource budget was consumed.

    ## Pagination and retries

    Cursor pagination is operation-specific, not universal. Contacts without search,
    tasks, opportunities, message history and campaign lists support cursors.
    Conversation lists, appointment rosters and discovery collections are bounded.
    Follow meta.hasMore and pass meta.cursor unchanged with the same location and
    filters; an empty filtered page does not necessarily mean exhaustion. Search
    and exact-email lookup do not support cursor traversal. Counts can be bounded.

    No automatic retry guarantee applies to every write. General OAuth writes and
    standard campaign writes require their documented Idempotency-Key; legacy and
    general Standard v2 writes retain their existing retry contract. See
    docs/integrations/api-behavior-contract.md for the complete compatibility table.

    ## Timestamps

    Timestamp formats are operation-specific. Booking slot times use Unix milliseconds;
    other fields may use ISO 8601 strings. Follow the individual field schemas.

    ## IDs

    All resource IDs are opaque strings (Convex document IDs). Treat them as unique identifiers
    without assuming any internal structure.

    ## Webhook delivery headers

    Outbound webhook deliveries always include the following request headers:

    - `Content-Type: application/json`
    - `User-Agent: Seedly-CRM-Webhook/1.0`
    - `X-Webhook-Signature: sha256={hex}` - HMAC-SHA256 of the raw request body
      using your subscription `secret`. The signed material is exactly
      `JSON.stringify(payload)` - i.e. the raw body bytes - and nothing else.
      This is the authoritative integrity + authenticity signal.
    - `X-Webhook-Signature-V2: sha256={hex}` - optional, additive. HMAC-SHA256 of
      `{X-Webhook-Timestamp}.{rawBodyBytes}` (a literal `.` joins them) using the
      same subscription `secret`. Because the timestamp is inside the signed
      material, verifying v2 lets a receiver reject a replayed or
      timestamp-rewritten delivery. Prefer v2 when you want replay protection;
      v1 (`X-Webhook-Signature`) is unchanged and still sent for existing receivers.
    - `X-Webhook-Event: {event.name}` - e.g. `contact.created`, `message.received`.
    - `X-Webhook-Delivery: {deliveryLogId}` - unique per HTTP attempt; changes on
      retry of the same business event.
    - `X-Webhook-Timestamp: {epoch_ms}` - wall-clock millisecond timestamp at
      send time. **Informational only.** It is NOT part of the HMAC input -
      the body's `timestamp` field is what was actually signed. Receivers who
      wish to enforce a replay window may compare this header against their
      own clock and reject deliveries with excessive skew.
    - `X-Webhook-Event-Id: {id}` - stable identifier for the upstream business
      event, derived from the payload's primary entity id (`messageId` →
      `contactId` → `dealId` → `invoiceId` → `conversationId` → `appointmentId`),
      with a fallback of `{eventType}:{deliveryLogId}` when no entity id is
      present. Use this header (not `X-Webhook-Delivery`) for cross-retry
      de-duplication: `X-Webhook-Delivery` changes on retry, `X-Webhook-Event-Id`
      does not.
  contact:
    name: Seedly CRM
    url: https://github.com/YOUR_ORG/seedly-crm

servers:
  - url: https://{deployment}.convex.site
    description: Convex deployment
    variables:
      deployment:
        default: your-deployment
        description: Your Convex deployment subdomain (found in Convex dashboard > Settings > URL)

security:
  - bearerAuth: []

tags:
  - name: Documents
    description: Documents, templates, flows, delivery and certificates
  - name: Estimates
    description: Estimate roster, delivery and conversion
  - name: Recurring Invoices
    description: Customer recurring invoice schedules
  - name: Commerce Catalog
    description: Products, pricing, bundles and discount codes
  - name: Files
    description: File metadata, authenticated upload and download
  - name: Invoices
    description: Invoice lifecycle, delivery and reminders
  - name: Payments
    description: Payment history, offline records, refunds and payment links
  - name: Contacts
    description: Manage CRM contacts
  - name: Conversations
    description: Manage conversations and messages
  - name: Calendars
    description: Calendars, appointment types, availability, and appointments
  - name: Webhooks
    description: Manage outbound webhook subscriptions
  - name: Campaigns
    description: Create email campaigns from a stored layout plus content HTML
  - name: Sub-Accounts
    description: Sub-account discovery for agency-scoped keys
  - name: Verified appointments
    description: |
      One caller's own appointments, for a booking assistant. Requires the caller
      to present identifiers that resolve to a single contact, and never returns
      a roster.
  - name: Add-on routes
    description: |
      Routes contributed by installed add-ons. Empty unless an add-on is installed.
      Call GET /api/v1/ext to see what this install exposes.
  - name: Conversational booking
    description: |
      Two purpose-built reads for an AI setter that books jobs over chat. One
      answers price questions, the other answers "does this customer already
      have an approved quote". They are separate scopes because they are not
      the same kind of data.

paths:
  /api/v1/calendars/{id}/appointment-types:
    get:
      x-seedly-oauth-scope: "calendars:read"
      x-seedly-standard-scope: "calendars:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "catalogGetApiV1CalendarsIdAppointmentTypes"
      summary: "GET /api/v1/calendars/{id}/appointment-types"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operations only. No legacy API key/CloseBot or restricted record grants. Parent and secondary references are checked live before retry receipts. Configuration only; DELETE requires no appointments, active unexpired OAuth slot holds, booking links or booking-provenance submissions, otherwise 409 with no mutation or provider cleanup. The existing native destructive cascade is not exposed. JSON write bodies max65536 bytes; stable Idempotency-Key required. Booking form references require forms:read. No immediate sends, provider calls, payments or calendar creation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192,"minLength":1}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AppointmentTypeCatalog"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflicting request or dependent type deletion."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
    post:
      x-seedly-oauth-scope: "calendars:write"
      x-seedly-standard-scope: "calendars:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "catalogPostApiV1CalendarsIdAppointmentTypes"
      summary: "POST /api/v1/calendars/{id}/appointment-types"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operations only. No legacy API key/CloseBot or restricted record grants. Parent and secondary references are checked live before retry receipts. Configuration only; DELETE requires no appointments, active unexpired OAuth slot holds, booking links or booking-provenance submissions, otherwise 409 with no mutation or provider cleanup. The existing native destructive cascade is not exposed. JSON write bodies max65536 bytes; stable Idempotency-Key required. Booking form references require forms:read. No immediate sends, provider calls, payments or calendar creation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","created"],"properties":{"id":{"type":"string"},"created":{"const":true}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflicting request or dependent type deletion."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentTypeCatalogCreate"}}}}
  /api/v1/appointment-types/{id}:
    get:
      x-seedly-oauth-scope: "calendars:read"
      x-seedly-standard-scope: "calendars:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "catalogGetApiV1AppointmentTypesId"
      summary: "GET /api/v1/appointment-types/{id}"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operations only. No legacy API key/CloseBot or restricted record grants. Parent and secondary references are checked live before retry receipts. Configuration only; DELETE requires no appointments, active unexpired OAuth slot holds, booking links or booking-provenance submissions, otherwise 409 with no mutation or provider cleanup. The existing native destructive cascade is not exposed. JSON write bodies max65536 bytes; stable Idempotency-Key required. Booking form references require forms:read. No immediate sends, provider calls, payments or calendar creation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/AppointmentTypeCatalog"}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflicting request or dependent type deletion."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
    patch:
      x-seedly-oauth-scope: "calendars:write"
      x-seedly-standard-scope: "calendars:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "catalogPatchApiV1AppointmentTypesId"
      summary: "PATCH /api/v1/appointment-types/{id}"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operations only. No legacy API key/CloseBot or restricted record grants. Parent and secondary references are checked live before retry receipts. Configuration only; DELETE requires no appointments, active unexpired OAuth slot holds, booking links or booking-provenance submissions, otherwise 409 with no mutation or provider cleanup. The existing native destructive cascade is not exposed. JSON write bodies max65536 bytes; stable Idempotency-Key required. Booking form references require forms:read. No immediate sends, provider calls, payments or calendar creation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"const":true}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflicting request or dependent type deletion."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentTypeCatalogUpdate"}}}}
    delete:
      x-seedly-oauth-scope: "calendars:delete"
      x-seedly-standard-scope: "calendars:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "catalogDeleteApiV1AppointmentTypesId"
      summary: "DELETE /api/v1/appointment-types/{id}"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operations only. No legacy API key/CloseBot or restricted record grants. Parent and secondary references are checked live before retry receipts. Configuration only; DELETE requires no appointments, active unexpired OAuth slot holds, booking links or booking-provenance submissions, otherwise 409 with no mutation or provider cleanup. The existing native destructive cascade is not exposed. JSON write bodies max65536 bytes; stable Idempotency-Key required. Booking form references require forms:read. No immediate sends, provider calls, payments or calendar creation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","deleted"],"properties":{"id":{"type":"string"},"deleted":{"const":true}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflicting request or dependent type deletion."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
  /api/v1/calendars/{id}/services:
    get:
      x-seedly-oauth-scope: "calendars:read"
      x-seedly-standard-scope: "calendars:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "catalogGetApiV1CalendarsIdServices"
      summary: "GET /api/v1/calendars/{id}/services"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operations only. No legacy API key/CloseBot or restricted record grants. Parent and secondary references are checked live before retry receipts. Price writes require priceUnit major and never rewrite stored price units on metadata-only edits. Staff assignment requires users:read and live member access. Service deletion preserves historical appointments. JSON write bodies max65536 bytes; stable Idempotency-Key required. Booking form references require forms:read. No immediate sends, provider calls, payments or calendar creation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192,"minLength":1}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CalendarServiceCatalog"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflicting request or dependent type deletion."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
    post:
      x-seedly-oauth-scope: "calendars:write"
      x-seedly-standard-scope: "calendars:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "catalogPostApiV1CalendarsIdServices"
      summary: "POST /api/v1/calendars/{id}/services"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operations only. No legacy API key/CloseBot or restricted record grants. Parent and secondary references are checked live before retry receipts. Price writes require priceUnit major and never rewrite stored price units on metadata-only edits. Staff assignment requires users:read and live member access. Service deletion preserves historical appointments. JSON write bodies max65536 bytes; stable Idempotency-Key required. Booking form references require forms:read. No immediate sends, provider calls, payments or calendar creation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","created"],"properties":{"id":{"type":"string"},"created":{"const":true}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflicting request or dependent type deletion."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarServiceCatalogCreate"}}}}
  /api/v1/services/{id}:
    get:
      x-seedly-oauth-scope: "calendars:read"
      x-seedly-standard-scope: "calendars:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "catalogGetApiV1ServicesId"
      summary: "GET /api/v1/services/{id}"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operations only. No legacy API key/CloseBot or restricted record grants. Parent and secondary references are checked live before retry receipts. Price writes require priceUnit major and never rewrite stored price units on metadata-only edits. Staff assignment requires users:read and live member access. Service deletion preserves historical appointments. JSON write bodies max65536 bytes; stable Idempotency-Key required. Booking form references require forms:read. No immediate sends, provider calls, payments or calendar creation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/CalendarServiceCatalog"}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflicting request or dependent type deletion."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
    patch:
      x-seedly-oauth-scope: "calendars:write"
      x-seedly-standard-scope: "calendars:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "catalogPatchApiV1ServicesId"
      summary: "PATCH /api/v1/services/{id}"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operations only. No legacy API key/CloseBot or restricted record grants. Parent and secondary references are checked live before retry receipts. Price writes require priceUnit major and never rewrite stored price units on metadata-only edits. Staff assignment requires users:read and live member access. Service deletion preserves historical appointments. JSON write bodies max65536 bytes; stable Idempotency-Key required. Booking form references require forms:read. No immediate sends, provider calls, payments or calendar creation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"const":true}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflicting request or dependent type deletion."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarServiceCatalogUpdate"}}}}
    delete:
      x-seedly-oauth-scope: "calendars:delete"
      x-seedly-standard-scope: "calendars:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "catalogDeleteApiV1ServicesId"
      summary: "DELETE /api/v1/services/{id}"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operations only. No legacy API key/CloseBot or restricted record grants. Parent and secondary references are checked live before retry receipts. Price writes require priceUnit major and never rewrite stored price units on metadata-only edits. Staff assignment requires users:read and live member access. Service deletion preserves historical appointments. JSON write bodies max65536 bytes; stable Idempotency-Key required. Booking form references require forms:read. No immediate sends, provider calls, payments or calendar creation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","deleted"],"properties":{"id":{"type":"string"},"deleted":{"const":true}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflicting request or dependent type deletion."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
  /api/v1/calendars/{id}/service-categories:
    get:
      x-seedly-oauth-scope: "calendars:read"
      x-seedly-standard-scope: "calendars:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "catalogGetApiV1CalendarsIdServiceCategories"
      summary: "GET /api/v1/calendars/{id}/service-categories"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operations only. No legacy API key/CloseBot or restricted record grants. Parent and secondary references are checked live before retry receipts. Deletion accepts a durable category-detach job, requiring calendars:write permission for the services PATCH operation in addition to calendars:delete. Parent removal fences new references. JSON write bodies max65536 bytes; stable Idempotency-Key required. Booking form references require forms:read. No immediate sends, provider calls, payments or calendar creation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192,"minLength":1}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ServiceCategoryCatalog"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflicting request or dependent type deletion."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
    post:
      x-seedly-oauth-scope: "calendars:write"
      x-seedly-standard-scope: "calendars:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "catalogPostApiV1CalendarsIdServiceCategories"
      summary: "POST /api/v1/calendars/{id}/service-categories"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operations only. No legacy API key/CloseBot or restricted record grants. Parent and secondary references are checked live before retry receipts. Deletion accepts a durable category-detach job, requiring calendars:write permission for the services PATCH operation in addition to calendars:delete. Parent removal fences new references. JSON write bodies max65536 bytes; stable Idempotency-Key required. Booking form references require forms:read. No immediate sends, provider calls, payments or calendar creation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","created"],"properties":{"id":{"type":"string"},"created":{"const":true}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflicting request or dependent type deletion."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceCategoryCatalogCreate"}}}}
  /api/v1/service-categories/{id}:
    get:
      x-seedly-oauth-scope: "calendars:read"
      x-seedly-standard-scope: "calendars:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "catalogGetApiV1ServiceCategoriesId"
      summary: "GET /api/v1/service-categories/{id}"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operations only. No legacy API key/CloseBot or restricted record grants. Parent and secondary references are checked live before retry receipts. Deletion accepts a durable category-detach job, requiring calendars:write permission for the services PATCH operation in addition to calendars:delete. Parent removal fences new references. JSON write bodies max65536 bytes; stable Idempotency-Key required. Booking form references require forms:read. No immediate sends, provider calls, payments or calendar creation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/ServiceCategoryCatalog"}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflicting request or dependent type deletion."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
    patch:
      x-seedly-oauth-scope: "calendars:write"
      x-seedly-standard-scope: "calendars:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "catalogPatchApiV1ServiceCategoriesId"
      summary: "PATCH /api/v1/service-categories/{id}"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operations only. No legacy API key/CloseBot or restricted record grants. Parent and secondary references are checked live before retry receipts. Deletion accepts a durable category-detach job, requiring calendars:write permission for the services PATCH operation in addition to calendars:delete. Parent removal fences new references. JSON write bodies max65536 bytes; stable Idempotency-Key required. Booking form references require forms:read. No immediate sends, provider calls, payments or calendar creation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"const":true}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflicting request or dependent type deletion."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceCategoryCatalogUpdate"}}}}
    delete:
      x-seedly-oauth-scope: "calendars:delete"
      x-seedly-standard-scope: "calendars:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "catalogDeleteApiV1ServiceCategoriesId"
      summary: "DELETE /api/v1/service-categories/{id}"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operations only. No legacy API key/CloseBot or restricted record grants. Parent and secondary references are checked live before retry receipts. Deletion accepts a durable category-detach job, requiring calendars:write permission for the services PATCH operation in addition to calendars:delete. Parent removal fences new references. JSON write bodies max65536 bytes; stable Idempotency-Key required. Booking form references require forms:read. No immediate sends, provider calls, payments or calendar creation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","deleted","jobId"],"properties":{"id":{"type":"string"},"deleted":{"const":true},"jobId":{"type":"string"}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflicting request or dependent type deletion."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
  /api/v1/calendars/{id}/services/reorder:
    post:
      x-seedly-oauth-scope: "calendars:write"
      x-seedly-standard-scope: "calendars:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "catalogPostApiV1CalendarsIdServicesReorder"
      summary: "POST /api/v1/calendars/{id}/services/reorder"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operations only. No legacy API key/CloseBot or restricted record grants. Parent and secondary references are checked live before retry receipts. Price writes require priceUnit major and never rewrite stored price units on metadata-only edits. Staff assignment requires users:read and live member access. Service deletion preserves historical appointments. JSON write bodies max65536 bytes; stable Idempotency-Key required. Booking form references require forms:read. No immediate sends, provider calls, payments or calendar creation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"const":true}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflicting request or dependent type deletion."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["serviceIds"],"properties":{"serviceIds":{"type":"array","minItems":1,"maxItems":100,"uniqueItems":true,"items":{"type":"string"}}}}}}}
  /api/v1/service-category-deletions/{id}:
    get:
      x-seedly-oauth-scope: "calendars:delete"
      x-seedly-standard-scope: "calendars:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "catalogGetApiV1ServiceCategoryDeletionsId"
      summary: "GET /api/v1/service-category-deletions/{id}"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operations only. No legacy API key/CloseBot or restricted record grants. Parent and secondary references are checked live before retry receipts. Same integration only; resume rechecks original delete and service PATCH authority, replaces OAuth ceiling, and schedules bounded 100-row/1MB batches. Paused or stalled runs can resume; no cancel. JSON write bodies max65536 bytes; stable Idempotency-Key required. Booking form references require forms:read. No immediate sends, provider calls, payments or calendar creation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/ServiceCategoryDeletionJob"}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflicting request or dependent type deletion."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
  /api/v1/service-category-deletions/{id}/resume:
    post:
      x-seedly-oauth-scope: "calendars:delete"
      x-seedly-standard-scope: "calendars:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "catalogPostApiV1ServiceCategoryDeletionsIdResume"
      summary: "POST /api/v1/service-category-deletions/{id}/resume"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operations only. No legacy API key/CloseBot or restricted record grants. Parent and secondary references are checked live before retry receipts. Same integration only; resume rechecks original delete and service PATCH authority, replaces OAuth ceiling, and schedules bounded 100-row/1MB batches. Paused or stalled runs can resume; no cancel. JSON write bodies max65536 bytes; stable Idempotency-Key required. Booking form references require forms:read. No immediate sends, provider calls, payments or calendar creation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","resumed"],"properties":{"id":{"type":"string"},"resumed":{"const":true}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflicting request or dependent type deletion."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}
  /api/v1/calendars/{id}/settings:
    get:
      x-seedly-oauth-scope: "calendars:read"
      x-seedly-standard-scope: "calendars:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "calendarSettingsGet"
      summary: "GET /api/v1/calendars/{id}/settings"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operation. No legacy API key, CloseBot or restricted record grant access. Credentials, provider tokens and connection lifecycle are never read or written here. On read, member fields need users:read and email template bindings need templates:read, or they are omitted. Member references need users:read and active users with live location access; email template references need templates:read. A sync direction change requires an already connected calendar and can enqueue the native Google watch setup. Notification recipient routing is not accepted. Enabling a notification, changing its subject, body or timing, or binding an email template also needs calendars:send; turning a notification off or clearing a template binding does not. Writes require a stable Idempotency-Key; body limit 128 KiB. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflict with current state or an earlier idempotency request."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
    patch:
      x-seedly-oauth-scope: "calendars:write"
      x-seedly-standard-scope: "calendars:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "calendarSettingsPatch"
      summary: "PATCH /api/v1/calendars/{id}/settings"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operation. No legacy API key, CloseBot or restricted record grant access. Credentials, provider tokens and connection lifecycle are never read or written here. On read, member fields need users:read and email template bindings need templates:read, or they are omitted. Member references need users:read and active users with live location access; email template references need templates:read. A sync direction change requires an already connected calendar and can enqueue the native Google watch setup. Notification recipient routing is not accepted. Enabling a notification, changing its subject, body or timing, or binding an email template also needs calendars:send; turning a notification off or clearing a template binding does not. Writes require a stable Idempotency-Key; body limit 128 KiB. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"type":"boolean"}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflict with current state or an earlier idempotency request."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"minProperties":1,"properties":{"type":{"enum":["personal","round_robin","collective","class"]},"color":{"type":"string","maxLength":100},"meetingLinkType":{"enum":["none","zoom","google_meet"]},"roundRobinMethod":{"enum":["availability","equal_distribution","priority"]},"roundRobinMembers":{"type":"array","maxItems":100,"items":{"type":"object","additionalProperties":false,"required":["userId"],"properties":{"userId":{"type":"string"},"priority":{"type":"integer","minimum":0}}}},"collectiveMembers":{"type":"array","maxItems":100,"items":{"type":"string"}},"collectivePrimaryOwner":{"type":"string"},"locationOptions":{"type":"array","maxItems":20,"items":{"type":"object"}},"scheduling":{"type":"object","additionalProperties":false,"properties":{"bufferBefore":{"type":"integer","minimum":0},"bufferAfter":{"type":"integer","minimum":0},"minNotice":{"type":"integer","minimum":0},"maxAdvance":{"type":"integer","minimum":0},"maxPerSlot":{"type":"integer","minimum":0},"maxPerDay":{"type":"integer","minimum":0},"changeCutoffHours":{"type":"integer","minimum":0},"embedEnabled":{"type":"boolean"},"rescheduleEnabled":{"type":"boolean"},"cancelEnabled":{"type":"boolean"},"requirePhone":{"type":"boolean"}}},"widget":{"type":"object","additionalProperties":false,"properties":{"primaryColor":{"type":"string"},"backgroundColor":{"type":"string"},"fontFamily":{"type":"string"},"headingFontFamily":{"type":"string"},"logoUrl":{"type":"string","format":"uri"},"layout":{"enum":["list","grid"]},"dateTimeLayout":{"enum":["stepped","split"]},"hideHeader":{"type":"boolean"},"customCss":{"type":"string","maxLength":20000}}},"brandStyleId":{"type":["string","null"]},"stepOrder":{"type":"string","maxLength":200},"notifications":{"type":"object","description":"Notification templates keyed by template name. Supplied fields merge into that template and other templates are kept. A blank body, subject or sendBefore clears that override, so the default applies, and clearing a stored value counts as a change. Owner and team recipient routing is not accepted. Anything other than turning a notification off needs calendars:send."},"emailTemplates":{"type":"object","description":"A non-null binding needs calendars:send and templates:read.","additionalProperties":{"type":["string","null"]}},"googleSyncDirection":{"enum":["push","pull","both"]},"outlookSyncDirection":{"enum":["one_way_read","one_way_write","two_way"]}}}}}}
  /api/v1/calendars/{id}/external-sync:
    patch:
      x-seedly-oauth-scope: "calendars:sync"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: "calendarExternalSyncPatch"
      summary: "PATCH /api/v1/calendars/{id}/external-sync"
      tags: ["Integrations"]
      description: "OAuth only. Turns sync on or off with the consenting person's own connected Google or Outlook calendar. That person must own the calendar and hold the connection. A Standard key or another person's grant is refused. Connecting a mailbox stays in the dashboard, and no provider token is returned."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["id","provider","enabled"],"properties":{"id":{"type":"string"},"provider":{"type":"string","enum":["google","outlook"]},"enabled":{"type":"boolean"}}}}}}}},"400":{"description":"Invalid request."},"401":{"description":"Invalid credential."},"403":{"description":"Missing scope, or not the mailbox owner."},"404":{"description":"Calendar unavailable."},"409":{"description":"Idempotency conflict, or a cascade deletion is open."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["provider","enabled"],"properties":{"provider":{"type":"string","enum":["google","outlook"]},"enabled":{"type":"boolean"}}}}}}
  /api/v1/calendars/{id}/notifications:
    patch:
      x-seedly-oauth-scope: "calendars:send"
      x-seedly-standard-scope: "calendars:send"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "calendarNotificationsPatch"
      summary: "PATCH /api/v1/calendars/{id}/notifications"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operation. No legacy API key, CloseBot or restricted record grant access. Sets the booking, reminder, cancellation and reschedule messages this calendar sends to customers and staff, and their timing. These are stored and sent on every later booking, so this is send authority and is separate from calendars:write. Nothing is sent by this request. Email template references need templates:read. Notification recipient routing is not accepted. Requires a stable Idempotency-Key; body limit 128 KiB."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"type":"boolean"}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflict with current state or an earlier idempotency request."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"minProperties":1,"properties":{"notifications":{"type":"object","description":"Notification templates keyed by template name. Supplied fields merge into that template and other templates are kept. A blank body, subject or sendBefore clears that override, so the default applies, and clearing a stored value counts as a change."},"emailTemplates":{"type":"object","additionalProperties":{"type":["string","null"]}}}}}}}
  /api/v1/calendars/{id}/payment-settings:
    patch:
      x-seedly-oauth-scope: "calendars:write"
      x-seedly-standard-scope: "calendars:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "calendarPaymentSettingsPatch"
      summary: "PATCH /api/v1/calendars/{id}/payment-settings"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operation. No legacy API key, CloseBot or restricted record grant access. Sets whether booking requires payment and the major-unit amount. An omitted amount or currency keeps the stored value. Requires a stable Idempotency-Key. No charge, Checkout session or refund is created by this change."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"type":"boolean"}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflict with current state or an earlier idempotency request."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["requirePayment"],"properties":{"requirePayment":{"type":"boolean"},"paymentAmount":{"type":"number","exclusiveMinimum":0,"maximum":1000000000,"description":"Major currency units."},"paymentCurrency":{"type":"string","pattern":"^[a-z]{3}$"}}}}}}
  /api/v1/calendars/{id}/cascade-deletions:
    post:
      x-seedly-oauth-scope: "calendars:purge"
      x-seedly-standard-scope: "calendars:purge"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "calendarCascadeDeletionStart"
      summary: "POST /api/v1/calendars/{id}/cascade-deletions"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operation. No legacy API key, CloseBot or restricted record grant access. Requires calendars:purge exactly; calendars:delete never authorizes this. The parent is deactivated when accepted and removed last. Appointments, reminders, attendees, booking links and booking submissions are permanently deleted in bounded batches, active slot holds are released, and CRM-owned Google events and unpaid Checkout sessions are released through the native cleanup queue. No workflows, notifications or refunds are started. Batches reauthorize the original credential. Revocation pauses the job. A stable Idempotency-Key is required."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","jobId","accepted"],"properties":{"id":{"type":"string"},"jobId":{"type":"string"},"accepted":{"type":"boolean"}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflict with current state or an earlier idempotency request."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["confirmName","acknowledgePermanentDeletion"],"properties":{"confirmName":{"type":"string","description":"The current exact name of the record."},"acknowledgePermanentDeletion":{"const":true}}}}}}
  /api/v1/appointment-types/{id}/cascade-deletions:
    post:
      x-seedly-oauth-scope: "calendars:purge"
      x-seedly-standard-scope: "calendars:purge"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "appointmentTypeCascadeDeletionStart"
      summary: "POST /api/v1/appointment-types/{id}/cascade-deletions"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operation. No legacy API key, CloseBot or restricted record grant access. Requires calendars:purge exactly; calendars:delete never authorizes this. The parent is deactivated when accepted and removed last. Appointments, reminders, attendees, booking links and booking submissions are permanently deleted in bounded batches, active slot holds are released, and CRM-owned Google events and unpaid Checkout sessions are released through the native cleanup queue. No workflows, notifications or refunds are started. Batches reauthorize the original credential. Revocation pauses the job. A stable Idempotency-Key is required."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","jobId","accepted"],"properties":{"id":{"type":"string"},"jobId":{"type":"string"},"accepted":{"type":"boolean"}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflict with current state or an earlier idempotency request."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["confirmName","acknowledgePermanentDeletion"],"properties":{"confirmName":{"type":"string","description":"The current exact name of the record."},"acknowledgePermanentDeletion":{"const":true}}}}}}
  /api/v1/calendar-cascade-deletions/{id}:
    get:
      x-seedly-oauth-scope: "calendars:purge"
      x-seedly-standard-scope: "calendars:purge"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "calendarCascadeDeletionGet"
      summary: "GET /api/v1/calendar-cascade-deletions/{id}"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operation. No legacy API key, CloseBot or restricted record grant access. Progress for a job started by this same integration. Exposes counts and status, never a principal or secret."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","calendarId","appointmentTypeId","status","phase","pauseReason","appointmentsDeleted","holdsReleased","linksDeleted","submissionsDeleted","stalled","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"calendarId":{"type":"string"},"appointmentTypeId":{"type":["string","null"]},"status":{"enum":["running","paused","cancelled","complete"]},"phase":{"enum":["appointments","holds","links","submissions","cache","configuration"]},"pauseReason":{"enum":["authorization","reactivated","superseded",null]},"appointmentsDeleted":{"type":"integer"},"holdsReleased":{"type":"integer"},"linksDeleted":{"type":"integer"},"submissionsDeleted":{"type":"integer"},"stalled":{"type":"boolean"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflict with current state or an earlier idempotency request."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
  /api/v1/calendar-cascade-deletions/{id}/resume:
    post:
      x-seedly-oauth-scope: "calendars:purge"
      x-seedly-standard-scope: "calendars:purge"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "calendarCascadeDeletionResume"
      summary: "POST /api/v1/calendar-cascade-deletions/{id}/resume"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operation. No legacy API key, CloseBot or restricted record grant access. Same integration only. Resumes a paused or stalled job with current authority, replacing the stored OAuth ceiling and re-deactivating the parent if it was reactivated."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","resumed"],"properties":{"id":{"type":"string"},"resumed":{"type":"boolean"}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflict with current state or an earlier idempotency request."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}
  /api/v1/calendar-cascade-deletions/{id}/cancel:
    post:
      x-seedly-oauth-scope: "calendars:purge"
      x-seedly-standard-scope: "calendars:purge"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "calendarCascadeDeletionCancel"
      summary: "POST /api/v1/calendar-cascade-deletions/{id}/cancel"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operation. No legacy API key, CloseBot or restricted record grant access. Same integration only. Stops further deletion and restores the parent's prior active state. Rows already deleted are not restored."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","cancelled"],"properties":{"id":{"type":"string"},"cancelled":{"type":"boolean"}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflict with current state or an earlier idempotency request."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}
  /api/v1/appointments/{id}:
    patch:
      x-seedly-oauth-scope: "appointments:manage"
      x-seedly-standard-scope: "appointments:manage"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "appointmentUpdate"
      summary: "PATCH /api/v1/appointments/{id}"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operation. No legacy API key, CloseBot or restricted record grant access. Uses the native shared command, so workflow triggers, reminder rescheduling and Google, Outlook and Zoom updates are preserved and enqueued. Slot availability is not rechecked, matching a staff edit. A cancelled appointment cannot be changed here. Writes require a stable Idempotency-Key and return a receipt. Set notifyAttendees false to skip reschedule notifications."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"type":"boolean"}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflict with current state or an earlier idempotency request."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"minProperties":1,"properties":{"title":{"type":"string","minLength":1,"maxLength":500},"startTime":{"type":"integer","description":"Epoch milliseconds."},"endTime":{"type":"integer","description":"Epoch milliseconds."},"notes":{"type":"string","maxLength":10000},"selectedLocation":{"type":"object"},"guests":{"type":"array","maxItems":50,"items":{"type":"object"}},"notifyAttendees":{"type":"boolean"}}}}}}
  /api/v1/appointments/{id}/status:
    post:
      x-seedly-oauth-scope: "appointments:manage"
      x-seedly-standard-scope: "appointments:manage"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "appointmentStatusSet"
      summary: "POST /api/v1/appointments/{id}/status"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operation. No legacy API key, CloseBot or restricted record grant access. Uses the native shared command, so workflow triggers, reminder rescheduling and Google, Outlook and Zoom updates are preserved and enqueued. Slot availability is not rechecked, matching a staff edit. A cancelled appointment cannot be changed here. Writes require a stable Idempotency-Key and return a receipt. Sets scheduled, confirmed, completed or no_show. Cancellation uses the separately authorized cancel route, and a cancelled appointment is not reinstated. Repeating the current status is a no-op."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"type":"boolean"}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflict with current state or an earlier idempotency request."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["status"],"properties":{"status":{"enum":["scheduled","confirmed","completed","no_show"]},"notifyAttendees":{"type":"boolean"}}}}}}
  /api/v1/appointments/{id}/series:
    get:
      x-seedly-oauth-scope: "appointments:read"
      x-seedly-standard-scope: "appointments:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "appointmentSeriesList"
      summary: "GET /api/v1/appointments/{id}/series"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operation. No legacy API key, CloseBot or restricted record grant access. Occurrence timing and status only. Paged; filtered pages can be empty while hasMore is true. Returns 404 for an appointment outside a series."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","seriesIndex","startTime","endTime","status","isSeriesException"],"properties":{"id":{"type":"string"},"seriesIndex":{"type":["integer","null"]},"startTime":{"type":"string"},"endTime":{"type":"string"},"status":{"type":"string"},"isSeriesException":{"type":"boolean"}}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflict with current state or an earlier idempotency request."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
    patch:
      x-seedly-oauth-scope: "appointments:manage"
      x-seedly-standard-scope: "appointments:manage"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "appointmentSeriesUpdate"
      summary: "PATCH /api/v1/appointments/{id}/series"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operation. No legacy API key, CloseBot or restricted record grant access. Uses the native shared command, so workflow triggers, reminder rescheduling and Google, Outlook and Zoom updates are preserved and enqueued. Slot availability is not rechecked, matching a staff edit. A cancelled appointment cannot be changed here. Writes require a stable Idempotency-Key and return a receipt. Scope all covers upcoming non-exception occurrences; this_and_following covers this start and later; this marks an exception. Scoped edits change only upcoming scheduled or confirmed occurrences, and a scoped status must be scheduled or confirmed. A series above 200 occurrences or 2 MB is refused whole. A series time change needs both startTime and endTime. Series edits send no per-occurrence notification. Result updated is the occurrence count."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"type":"integer"}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflict with current state or an earlier idempotency request."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["scope"],"properties":{"title":{"type":"string","minLength":1,"maxLength":500},"startTime":{"type":"integer","description":"Epoch milliseconds."},"endTime":{"type":"integer","description":"Epoch milliseconds."},"notes":{"type":"string","maxLength":10000},"scope":{"enum":["this","all","this_and_following"]},"location":{"type":"string","maxLength":2000},"status":{"enum":["scheduled","confirmed","completed","no_show"]}}}}}}
  /api/v1/appointments/{id}/series/cancel:
    post:
      x-seedly-oauth-scope: "appointments:delete"
      x-seedly-standard-scope: "appointments:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "appointmentSeriesCancel"
      summary: "POST /api/v1/appointments/{id}/series/cancel"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operation. No legacy API key, CloseBot or restricted record grant access. Cancels under appointments:delete. Only upcoming scheduled or confirmed occurrences are cancelled; past, completed and no-show rows are left alone. Each cancelled occurrence gets the staff teardown through native queues: slot release, Zoom and Outlook deletion, unpaid Checkout expiry, activity, rep notice and its own workflow trigger, because each appointment was cancelled. The customer gets one cancellation notice for the request, using the standard notice for the target occurrence, because there is no series template. It names that occurrence, not every date. No refund is made. A series above 100 occurrences or 2 MB is refused whole. Requires a stable Idempotency-Key. Result cancelled is the occurrence count."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","cancelled"],"properties":{"id":{"type":"string"},"cancelled":{"type":"integer"}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflict with current state or an earlier idempotency request."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["scope"],"properties":{"scope":{"enum":["this","all","this_and_following"]},"reason":{"type":"string","maxLength":1000}}}}}}
  /api/v1/appointments/{id}/attendees:
    get:
      x-seedly-oauth-scope: "appointments:read"
      x-seedly-standard-scope: "appointments:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "appointmentAttendeesList"
      summary: "GET /api/v1/appointments/{id}/attendees"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operation. No legacy API key, CloseBot or restricted record grant access. Class and event registrations. Also requires contacts:read approval. Returns contact IDs without profile data. Paged."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","appointmentId","contactId","status","registeredAt","cancelledAt"],"properties":{"id":{"type":"string"},"appointmentId":{"type":"string"},"contactId":{"type":"string"},"status":{"type":"string"},"registeredAt":{"type":"string"},"cancelledAt":{"type":["string","null"]}}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflict with current state or an earlier idempotency request."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
  /api/v1/appointment-attendees/{id}:
    patch:
      x-seedly-oauth-scope: "appointments:manage"
      x-seedly-standard-scope: "appointments:manage"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "appointmentAttendeeUpdate"
      summary: "PATCH /api/v1/appointment-attendees/{id}"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operation. No legacy API key, CloseBot or restricted record grant access. Marks a registration registered, attended or no_show. Cancelling uses the separate cancel route. A cancelled registration is not revived. Requires a stable Idempotency-Key."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"type":"boolean"}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflict with current state or an earlier idempotency request."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["status"],"properties":{"status":{"enum":["registered","attended","no_show"]}}}}}}
  /api/v1/calendars/{id}/date-overrides/bulk:
    post:
      x-seedly-oauth-scope: "calendars:write"
      x-seedly-standard-scope: "calendars:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "calendarDateOverridesBulk"
      summary: "POST /api/v1/calendars/{id}/date-overrides/bulk"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operation. No legacy API key, CloseBot or restricted record grant access. Adds up to 100 date overrides and skips dates that already have one. Requires a stable Idempotency-Key."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","added","skipped"],"properties":{"id":{"type":"string"},"added":{"type":"integer"},"skipped":{"type":"integer"}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflict with current state or an earlier idempotency request."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["overrides"],"properties":{"overrides":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"object","additionalProperties":false,"required":["date","isUnavailable"],"properties":{"date":{"type":"string","format":"date"},"isUnavailable":{"type":"boolean"},"reason":{"type":"string","maxLength":1000}}}}}}}}}
  /api/v1/calendars/{id}/booking-links:
    get:
      x-seedly-oauth-scope: "calendars:read"
      x-seedly-standard-scope: "calendars:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "calendarBookingLinksList"
      summary: "GET /api/v1/calendars/{id}/booking-links"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operation. No legacy API key, CloseBot or restricted record grant access. Link metadata only. The private link URL is never listed. contactId is present only with contacts:read approval, and returned contact IDs are read-audited. Paged."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflict with current state or an earlier idempotency request."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
    post:
      x-seedly-oauth-scope: "calendars:write"
      x-seedly-standard-scope: "calendars:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "calendarBookingLinkCreate"
      summary: "POST /api/v1/calendars/{id}/booking-links"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operation. No legacy API key, CloseBot or restricted record grant access. Creates a private customer booking link and returns its relative URL. A contact reference also needs contacts:read. No message is sent. Requires a stable Idempotency-Key; a replay returns the same link while it is usable."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","url"],"properties":{"id":{"type":"string"},"url":{"type":"string"}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflict with current state or an earlier idempotency request."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"appointmentTypeId":{"type":"string"},"contactId":{"type":"string"},"expiresInHours":{"type":"integer","minimum":0,"maximum":8760,"default":72},"maxUses":{"type":"integer","minimum":1,"maximum":10000,"default":1}}}}}}
  /api/v1/booking-links/{id}:
    delete:
      x-seedly-oauth-scope: "calendars:delete"
      x-seedly-standard-scope: "calendars:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "calendarBookingLinkRevoke"
      summary: "DELETE /api/v1/booking-links/{id}"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operation. No legacy API key, CloseBot or restricted record grant access. Expires a booking link immediately. Requires a stable Idempotency-Key."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","revoked"],"properties":{"id":{"type":"string"},"revoked":{"type":"boolean"}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflict with current state or an earlier idempotency request."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
  /api/v1/appointment-attendees/{id}/cancel:
    post:
      x-seedly-oauth-scope: "appointments:delete"
      x-seedly-standard-scope: "appointments:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "appointmentAttendeeCancel"
      summary: "POST /api/v1/appointment-attendees/{id}/cancel"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operation. No legacy API key, CloseBot or restricted record grant access. Cancels one registered seat on an upcoming class under appointments:delete. Records the native activity and notifies that attendee unless notifyAttendees is false. The attendee notice promises no refund, because seats carry no payment record. Other attendees hear nothing and the class continues. No refund is made. Requires a stable Idempotency-Key."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","cancelled"],"properties":{"id":{"type":"string"},"cancelled":{"type":"boolean"}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflict with current state or an earlier idempotency request."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"reason":{"type":"string","maxLength":1000},"notifyAttendees":{"type":"boolean"}}}}}}

  /api/v1/company-folders:
    get:
      x-seedly-oauth-scope: "companies:read"
      x-seedly-standard-scope: "companies:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listCompanyFolders
      summary: "Get company-folders"
      tags: ["Organization"]
      description: "Explicit location-wide Standard v2 or OAuth operation approval only; legacy keys, CloseBot and restricted record grants gain no access. Every write requires a stable Idempotency-Key and rechecks current authority and tenant references before returning a receipt. No caller role is fabricated and Standard creators are attribution only. Cursor pagination defaults to 50, maximum 100, cursor 8192 characters; order is sortOrder then insertion order. No 200-folder truncation. "
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses: {"200":{"description":"Safe metadata or durable receipt. Folder cleanup completion is reported by its job status.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationFolder"}},"meta":{"type":"object","additionalProperties":false,"properties":{"limit":{"type":"integer"},"hasMore":{"type":"boolean"},"cursor":{"type":["string","null"]}},"required":["limit","hasMore","cursor"]}},"required":["data"]}}}},"400":{"description":"Invalid payload or cursor."},"401":{"description":"Invalid or expired credential."},"403":{"description":"Missing or revoked approval."},"404":{"description":"Parent, record or job unavailable."},"409":{"description":"Request-key reuse conflict or duplicate custom value key."},"429":{"description":"Rate limited."}}
    post:
      x-seedly-oauth-scope: "companies:write"
      x-seedly-standard-scope: "companies:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createCompanyFolder
      summary: "Post company-folders"
      tags: ["Organization"]
      description: "Explicit location-wide Standard v2 or OAuth operation approval only; legacy keys, CloseBot and restricted record grants gain no access. Every write requires a stable Idempotency-Key and rechecks current authority and tenant references before returning a receipt. No caller role is fabricated and Standard creators are attribution only. "
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe metadata or durable receipt. Folder cleanup completion is reported by its job status.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"created":{"const":true}},"required":["id","created"]}},"required":["data"]}}}},"400":{"description":"Invalid payload or cursor."},"401":{"description":"Invalid or expired credential."},"403":{"description":"Missing or revoked approval."},"404":{"description":"Parent, record or job unavailable."},"409":{"description":"Request-key reuse conflict or duplicate custom value key."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":250},"parentId":{"type":"string"}},"required":["name"]}}}}
  /api/v1/company-folders/{id}:
    get:
      x-seedly-oauth-scope: "companies:read"
      x-seedly-standard-scope: "companies:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getCompanyFolder
      summary: "Get company-folders"
      tags: ["Organization"]
      description: "Explicit location-wide Standard v2 or OAuth operation approval only; legacy keys, CloseBot and restricted record grants gain no access. Every write requires a stable Idempotency-Key and rechecks current authority and tenant references before returning a receipt. No caller role is fabricated and Standard creators are attribution only. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe metadata or durable receipt. Folder cleanup completion is reported by its job status.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/OrganizationFolder"}},"required":["data"]}}}},"400":{"description":"Invalid payload or cursor."},"401":{"description":"Invalid or expired credential."},"403":{"description":"Missing or revoked approval."},"404":{"description":"Parent, record or job unavailable."},"409":{"description":"Request-key reuse conflict or duplicate custom value key."},"429":{"description":"Rate limited."}}
    patch:
      x-seedly-oauth-scope: "companies:write"
      x-seedly-standard-scope: "companies:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: renameCompanyFolder
      summary: "Patch company-folders"
      tags: ["Organization"]
      description: "Explicit location-wide Standard v2 or OAuth operation approval only; legacy keys, CloseBot and restricted record grants gain no access. Every write requires a stable Idempotency-Key and rechecks current authority and tenant references before returning a receipt. No caller role is fabricated and Standard creators are attribution only. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe metadata or durable receipt. Folder cleanup completion is reported by its job status.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"updated":{"const":true}},"required":["id","updated"]}},"required":["data"]}}}},"400":{"description":"Invalid payload or cursor."},"401":{"description":"Invalid or expired credential."},"403":{"description":"Missing or revoked approval."},"404":{"description":"Parent, record or job unavailable."},"409":{"description":"Request-key reuse conflict or duplicate custom value key."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":250}},"required":["name"]}}}}
    delete:
      x-seedly-oauth-scope: "companies:delete"
      x-seedly-standard-scope: "companies:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteCompanyFolder
      summary: "Delete company-folders"
      tags: ["Organization"]
      description: "Explicit location-wide Standard v2 or OAuth operation approval only; legacy keys, CloseBot and restricted record grants gain no access. Every write requires a stable Idempotency-Key and rechecks current authority and tenant references before returning a receipt. No caller role is fabricated and Standard creators are attribution only. Deletes the folder immediately and schedules bounded detach-to-root cleanup; companies/custom values and nested folders are not deleted. Requires matching write approval for the record folder-move operation. Receipt jobId identifies status/resume operations. Revoked authority pauses subsequent batches. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe metadata or durable receipt. Folder cleanup completion is reported by its job status.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"deleted":{"const":true},"jobId":{"type":"string"}},"required":["id","deleted","jobId"]}},"required":["data"]}}}},"400":{"description":"Invalid payload or cursor."},"401":{"description":"Invalid or expired credential."},"403":{"description":"Missing or revoked approval."},"404":{"description":"Parent, record or job unavailable."},"409":{"description":"Request-key reuse conflict or duplicate custom value key."},"429":{"description":"Rate limited."}}
  /api/v1/companies/{id}/folder:
    patch:
      x-seedly-oauth-scope: "companies:write"
      x-seedly-standard-scope: "companies:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: moveCompanyToFolder
      summary: "Patch companies"
      tags: ["Organization"]
      description: "Explicit location-wide Standard v2 or OAuth operation approval only; legacy keys, CloseBot and restricted record grants gain no access. Every write requires a stable Idempotency-Key and rechecks current authority and tenant references before returning a receipt. No caller role is fabricated and Standard creators are attribution only. folderId:null detaches to root. A non-null folder must currently exist in the same tenant. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe metadata or durable receipt. Folder cleanup completion is reported by its job status.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"updated":{"const":true}},"required":["id","updated"]}},"required":["data"]}}}},"400":{"description":"Invalid payload or cursor."},"401":{"description":"Invalid or expired credential."},"403":{"description":"Missing or revoked approval."},"404":{"description":"Parent, record or job unavailable."},"409":{"description":"Request-key reuse conflict or duplicate custom value key."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"folderId":{"type":["string","null"]}},"required":["folderId"]}}}}
  /api/v1/custom-value-folders:
    get:
      x-seedly-oauth-scope: "custom-values:read"
      x-seedly-standard-scope: "custom-values:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listCustomValueFolders
      summary: "Get custom-value-folders"
      tags: ["Organization"]
      description: "Explicit location-wide Standard v2 or OAuth operation approval only; legacy keys, CloseBot and restricted record grants gain no access. Every write requires a stable Idempotency-Key and rechecks current authority and tenant references before returning a receipt. No caller role is fabricated and Standard creators are attribution only. Cursor pagination defaults to 50, maximum 100, cursor 8192 characters; order is sortOrder then insertion order. No 200-folder truncation. "
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses: {"200":{"description":"Safe metadata or durable receipt. Folder cleanup completion is reported by its job status.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationFolder"}},"meta":{"type":"object","additionalProperties":false,"properties":{"limit":{"type":"integer"},"hasMore":{"type":"boolean"},"cursor":{"type":["string","null"]}},"required":["limit","hasMore","cursor"]}},"required":["data"]}}}},"400":{"description":"Invalid payload or cursor."},"401":{"description":"Invalid or expired credential."},"403":{"description":"Missing or revoked approval."},"404":{"description":"Parent, record or job unavailable."},"409":{"description":"Request-key reuse conflict or duplicate custom value key."},"429":{"description":"Rate limited."}}
    post:
      x-seedly-oauth-scope: "custom-values:write"
      x-seedly-standard-scope: "custom-values:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createCustomValueFolder
      summary: "Post custom-value-folders"
      tags: ["Organization"]
      description: "Explicit location-wide Standard v2 or OAuth operation approval only; legacy keys, CloseBot and restricted record grants gain no access. Every write requires a stable Idempotency-Key and rechecks current authority and tenant references before returning a receipt. No caller role is fabricated and Standard creators are attribution only. "
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe metadata or durable receipt. Folder cleanup completion is reported by its job status.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"created":{"const":true}},"required":["id","created"]}},"required":["data"]}}}},"400":{"description":"Invalid payload or cursor."},"401":{"description":"Invalid or expired credential."},"403":{"description":"Missing or revoked approval."},"404":{"description":"Parent, record or job unavailable."},"409":{"description":"Request-key reuse conflict or duplicate custom value key."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":250},"parentId":{"type":"string"}},"required":["name"]}}}}
  /api/v1/custom-value-folders/{id}:
    get:
      x-seedly-oauth-scope: "custom-values:read"
      x-seedly-standard-scope: "custom-values:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getCustomValueFolder
      summary: "Get custom-value-folders"
      tags: ["Organization"]
      description: "Explicit location-wide Standard v2 or OAuth operation approval only; legacy keys, CloseBot and restricted record grants gain no access. Every write requires a stable Idempotency-Key and rechecks current authority and tenant references before returning a receipt. No caller role is fabricated and Standard creators are attribution only. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe metadata or durable receipt. Folder cleanup completion is reported by its job status.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/OrganizationFolder"}},"required":["data"]}}}},"400":{"description":"Invalid payload or cursor."},"401":{"description":"Invalid or expired credential."},"403":{"description":"Missing or revoked approval."},"404":{"description":"Parent, record or job unavailable."},"409":{"description":"Request-key reuse conflict or duplicate custom value key."},"429":{"description":"Rate limited."}}
    patch:
      x-seedly-oauth-scope: "custom-values:write"
      x-seedly-standard-scope: "custom-values:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: renameCustomValueFolder
      summary: "Patch custom-value-folders"
      tags: ["Organization"]
      description: "Explicit location-wide Standard v2 or OAuth operation approval only; legacy keys, CloseBot and restricted record grants gain no access. Every write requires a stable Idempotency-Key and rechecks current authority and tenant references before returning a receipt. No caller role is fabricated and Standard creators are attribution only. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe metadata or durable receipt. Folder cleanup completion is reported by its job status.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"updated":{"const":true}},"required":["id","updated"]}},"required":["data"]}}}},"400":{"description":"Invalid payload or cursor."},"401":{"description":"Invalid or expired credential."},"403":{"description":"Missing or revoked approval."},"404":{"description":"Parent, record or job unavailable."},"409":{"description":"Request-key reuse conflict or duplicate custom value key."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":250}},"required":["name"]}}}}
    delete:
      x-seedly-oauth-scope: "custom-values:delete"
      x-seedly-standard-scope: "custom-values:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteCustomValueFolder
      summary: "Delete custom-value-folders"
      tags: ["Organization"]
      description: "Explicit location-wide Standard v2 or OAuth operation approval only; legacy keys, CloseBot and restricted record grants gain no access. Every write requires a stable Idempotency-Key and rechecks current authority and tenant references before returning a receipt. No caller role is fabricated and Standard creators are attribution only. Deletes the folder immediately and schedules bounded detach-to-root cleanup; companies/custom values and nested folders are not deleted. Requires matching write approval for the record folder-move operation. Receipt jobId identifies status/resume operations. Revoked authority pauses subsequent batches. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe metadata or durable receipt. Folder cleanup completion is reported by its job status.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"deleted":{"const":true},"jobId":{"type":"string"}},"required":["id","deleted","jobId"]}},"required":["data"]}}}},"400":{"description":"Invalid payload or cursor."},"401":{"description":"Invalid or expired credential."},"403":{"description":"Missing or revoked approval."},"404":{"description":"Parent, record or job unavailable."},"409":{"description":"Request-key reuse conflict or duplicate custom value key."},"429":{"description":"Rate limited."}}
  /api/v1/custom-values/{id}/folder:
    patch:
      x-seedly-oauth-scope: "custom-values:write"
      x-seedly-standard-scope: "custom-values:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: moveCustomValueToFolder
      summary: "Patch custom-values"
      tags: ["Organization"]
      description: "Explicit location-wide Standard v2 or OAuth operation approval only; legacy keys, CloseBot and restricted record grants gain no access. Every write requires a stable Idempotency-Key and rechecks current authority and tenant references before returning a receipt. No caller role is fabricated and Standard creators are attribution only. folderId:null detaches to root. A non-null folder must currently exist in the same tenant. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe metadata or durable receipt. Folder cleanup completion is reported by its job status.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"updated":{"const":true}},"required":["id","updated"]}},"required":["data"]}}}},"400":{"description":"Invalid payload or cursor."},"401":{"description":"Invalid or expired credential."},"403":{"description":"Missing or revoked approval."},"404":{"description":"Parent, record or job unavailable."},"409":{"description":"Request-key reuse conflict or duplicate custom value key."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"folderId":{"type":["string","null"]}},"required":["folderId"]}}}}
  /api/v1/custom-values/{id}/key:
    patch:
      x-seedly-oauth-scope: "custom-values:write"
      x-seedly-standard-scope: "custom-values:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: renameCustomValueKey
      summary: "Patch custom-values"
      tags: ["Organization"]
      description: "Explicit location-wide Standard v2 or OAuth operation approval only; legacy keys, CloseBot and restricted record grants gain no access. Every write requires a stable Idempotency-Key and rechecks current authority and tenant references before returning a receipt. No caller role is fabricated and Standard creators are attribution only. Native lowercase/underscore normalization and uniqueness checks apply. Preserves value and description. Existing {{custom_values.old_key}} references are not rewritten and may stop resolving; this does not grant template-editing or sending authority. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe metadata or durable receipt. Folder cleanup completion is reported by its job status.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"updated":{"const":true}},"required":["id","updated"]}},"required":["data"]}}}},"400":{"description":"Invalid payload or cursor."},"401":{"description":"Invalid or expired credential."},"403":{"description":"Missing or revoked approval."},"404":{"description":"Parent, record or job unavailable."},"409":{"description":"Request-key reuse conflict or duplicate custom value key."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"key":{"type":"string","minLength":1,"maxLength":50}},"required":["key"]}}}}
  /api/v1/company-folder-deletions/{id}:
    get:
      x-seedly-oauth-scope: "companies:delete"
      x-seedly-standard-scope: "companies:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getCompanyFolderDeletion
      summary: "Get company-folder-deletions"
      tags: ["Organization"]
      description: "Explicit location-wide Standard v2 or OAuth operation approval only; legacy keys, CloseBot and restricted record grants gain no access. Every write requires a stable Idempotency-Key and rechecks current authority and tenant references before returning a receipt. No caller role is fabricated and Standard creators are attribution only. Job is bound to its original integration principal and tenant. Status reveals progress, authority pause and a stalled lease after 120 seconds. Resume requires current deletion and record folder-move approvals; old worker versions cannot advance a resumed job. No cancellation is offered after parent deletion. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe metadata or durable receipt. Folder cleanup completion is reported by its job status.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/OrganizationFolderDeletionJob"}},"required":["data"]}}}},"400":{"description":"Invalid payload or cursor."},"401":{"description":"Invalid or expired credential."},"403":{"description":"Missing or revoked approval."},"404":{"description":"Parent, record or job unavailable."},"409":{"description":"Request-key reuse conflict or duplicate custom value key."},"429":{"description":"Rate limited."}}
  /api/v1/company-folder-deletions/{id}/resume:
    post:
      x-seedly-oauth-scope: "companies:delete"
      x-seedly-standard-scope: "companies:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: resumeCompanyFolderDeletion
      summary: "Post company-folder-deletions"
      tags: ["Organization"]
      description: "Explicit location-wide Standard v2 or OAuth operation approval only; legacy keys, CloseBot and restricted record grants gain no access. Every write requires a stable Idempotency-Key and rechecks current authority and tenant references before returning a receipt. No caller role is fabricated and Standard creators are attribution only. Job is bound to its original integration principal and tenant. Status reveals progress, authority pause and a stalled lease after 120 seconds. Resume requires current deletion and record folder-move approvals; old worker versions cannot advance a resumed job. No cancellation is offered after parent deletion. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe metadata or durable receipt. Folder cleanup completion is reported by its job status.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"resumed":{"const":true}},"required":["id","resumed"]}},"required":["data"]}}}},"400":{"description":"Invalid payload or cursor."},"401":{"description":"Invalid or expired credential."},"403":{"description":"Missing or revoked approval."},"404":{"description":"Parent, record or job unavailable."},"409":{"description":"Request-key reuse conflict or duplicate custom value key."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{},"required":[]}}}}
  /api/v1/custom-value-folder-deletions/{id}:
    get:
      x-seedly-oauth-scope: "custom-values:delete"
      x-seedly-standard-scope: "custom-values:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getCustomValueFolderDeletion
      summary: "Get custom-value-folder-deletions"
      tags: ["Organization"]
      description: "Explicit location-wide Standard v2 or OAuth operation approval only; legacy keys, CloseBot and restricted record grants gain no access. Every write requires a stable Idempotency-Key and rechecks current authority and tenant references before returning a receipt. No caller role is fabricated and Standard creators are attribution only. Job is bound to its original integration principal and tenant. Status reveals progress, authority pause and a stalled lease after 120 seconds. Resume requires current deletion and record folder-move approvals; old worker versions cannot advance a resumed job. No cancellation is offered after parent deletion. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe metadata or durable receipt. Folder cleanup completion is reported by its job status.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/OrganizationFolderDeletionJob"}},"required":["data"]}}}},"400":{"description":"Invalid payload or cursor."},"401":{"description":"Invalid or expired credential."},"403":{"description":"Missing or revoked approval."},"404":{"description":"Parent, record or job unavailable."},"409":{"description":"Request-key reuse conflict or duplicate custom value key."},"429":{"description":"Rate limited."}}
  /api/v1/custom-value-folder-deletions/{id}/resume:
    post:
      x-seedly-oauth-scope: "custom-values:delete"
      x-seedly-standard-scope: "custom-values:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: resumeCustomValueFolderDeletion
      summary: "Post custom-value-folder-deletions"
      tags: ["Organization"]
      description: "Explicit location-wide Standard v2 or OAuth operation approval only; legacy keys, CloseBot and restricted record grants gain no access. Every write requires a stable Idempotency-Key and rechecks current authority and tenant references before returning a receipt. No caller role is fabricated and Standard creators are attribution only. Job is bound to its original integration principal and tenant. Status reveals progress, authority pause and a stalled lease after 120 seconds. Resume requires current deletion and record folder-move approvals; old worker versions cannot advance a resumed job. No cancellation is offered after parent deletion. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe metadata or durable receipt. Folder cleanup completion is reported by its job status.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"resumed":{"const":true}},"required":["id","resumed"]}},"required":["data"]}}}},"400":{"description":"Invalid payload or cursor."},"401":{"description":"Invalid or expired credential."},"403":{"description":"Missing or revoked approval."},"404":{"description":"Parent, record or job unavailable."},"409":{"description":"Request-key reuse conflict or duplicate custom value key."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{},"required":[]}}}}
  /api/v1/contacts/{id}/restore:
    post:
      x-seedly-oauth-scope: "contacts:restore"
      x-seedly-standard-scope: "contacts:restore"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: startContactRestore
      tags: [Contacts]
      summary: startContactRestore
      description: Newly approved location-wide contacts:restore and contacts:read only. Dedicated consent includes conversation revival, cancelled appointment reinstatement and linked Google event recreation. No CRM campaign or workflow messages are requested. Contact row restores immediately; related rows finish in bounded jobs. Revocation pauses future batches with partial progress retained. Resume uses the current token ceiling and same integration owner. Cancellation does not undo completed changes. Stalled jobs can resume after the two-minute lease. Native contact edits remain available.
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {}}}}}
      responses: {"200": {"description": "Durable acceptance receipt or safe current job status.", "content": {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"type": "object", "additionalProperties": false, "required": ["id", "accepted", "contactId"], "properties": {"id": {"type": "string"}, "accepted": {"const": true}, "contactId": {"type": "string"}}}}}}}}, "400": {"description": "Invalid request; only empty JSON bodies accepted."}, "403": {"description": "Missing current specialty/contact-read authority or unsupported record restriction."}, "404": {"description": "Contact or same-owner job unavailable."}, "409": {"description": "Changed lifecycle, receipt conflict, or running job lease not expired."}, "429": {"description": "Rate limit exceeded."}}
  /api/v1/contact-restore-jobs/{id}:
    get:
      x-seedly-oauth-scope: "contacts:restore"
      x-seedly-standard-scope: "contacts:restore"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getContactRestoreJob
      tags: [Contacts]
      summary: getContactRestoreJob
      description: Newly approved location-wide contacts:restore and contacts:read only. Dedicated consent includes conversation revival, cancelled appointment reinstatement and linked Google event recreation. No CRM campaign or workflow messages are requested. Contact row restores immediately; related rows finish in bounded jobs. Revocation pauses future batches with partial progress retained. Resume uses the current token ceiling and same integration owner. Cancellation does not undo completed changes. Stalled jobs can resume after the two-minute lease. Native contact edits remain available.
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}]
      responses: {"200": {"description": "Durable acceptance receipt or safe current job status.", "content": {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"type": "object", "additionalProperties": false, "required": ["id", "contactId", "status", "phase", "conversationsRestored", "appointmentsRestored", "providerQueued", "providerCompleted", "providerSkipped", "childrenSkipped", "failureCode", "stalled", "partial", "createdAt", "updatedAt"], "properties": {"id": {"type": "string"}, "contactId": {"type": "string"}, "status": {"type": "string", "enum": ["running", "paused", "cancelled", "complete"]}, "phase": {"type": "string", "enum": ["conversations", "appointments", "complete"]}, "conversationsRestored": {"type": "integer", "minimum": 0}, "appointmentsRestored": {"type": "integer", "minimum": 0}, "providerQueued": {"type": "integer", "minimum": 0}, "providerCompleted": {"type": "integer", "minimum": 0}, "providerSkipped": {"type": "integer", "minimum": 0}, "childrenSkipped": {"type": "integer", "minimum": 0}, "failureCode": {"type": ["string", "null"]}, "stalled": {"type": "boolean"}, "partial": {"type": "boolean"}, "createdAt": {"type": "string", "format": "date-time"}, "updatedAt": {"type": "string", "format": "date-time"}}}}}}}}, "400": {"description": "Invalid request; only empty JSON bodies accepted."}, "403": {"description": "Missing current specialty/contact-read authority or unsupported record restriction."}, "404": {"description": "Contact or same-owner job unavailable."}, "409": {"description": "Changed lifecycle, receipt conflict, or running job lease not expired."}, "429": {"description": "Rate limit exceeded."}}
  /api/v1/contact-restore-jobs/{id}/resume:
    post:
      x-seedly-oauth-scope: "contacts:restore"
      x-seedly-standard-scope: "contacts:restore"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: resumeContactRestoreJob
      tags: [Contacts]
      summary: resumeContactRestoreJob
      description: Newly approved location-wide contacts:restore and contacts:read only. Dedicated consent includes conversation revival, cancelled appointment reinstatement and linked Google event recreation. No CRM campaign or workflow messages are requested. Contact row restores immediately; related rows finish in bounded jobs. Revocation pauses future batches with partial progress retained. Resume uses the current token ceiling and same integration owner. Cancellation does not undo completed changes. Stalled jobs can resume after the two-minute lease. Native contact edits remain available.
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {}}}}}
      responses: {"200": {"description": "Durable acceptance receipt or safe current job status.", "content": {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"type": "object", "additionalProperties": false, "required": ["id", "accepted"], "properties": {"id": {"type": "string"}, "accepted": {"const": true}}}}}}}}, "400": {"description": "Invalid request; only empty JSON bodies accepted."}, "403": {"description": "Missing current specialty/contact-read authority or unsupported record restriction."}, "404": {"description": "Contact or same-owner job unavailable."}, "409": {"description": "Changed lifecycle, receipt conflict, or running job lease not expired."}, "429": {"description": "Rate limit exceeded."}}
  /api/v1/contact-restore-jobs/{id}/cancel:
    post:
      x-seedly-oauth-scope: "contacts:restore"
      x-seedly-standard-scope: "contacts:restore"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: cancelContactRestoreJob
      tags: [Contacts]
      summary: cancelContactRestoreJob
      description: Newly approved location-wide contacts:restore and contacts:read only. Dedicated consent includes conversation revival, cancelled appointment reinstatement and linked Google event recreation. No CRM campaign or workflow messages are requested. Contact row restores immediately; related rows finish in bounded jobs. Revocation pauses future batches with partial progress retained. Resume uses the current token ceiling and same integration owner. Cancellation does not undo completed changes. Stalled jobs can resume after the two-minute lease. Native contact edits remain available.
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {}}}}}
      responses: {"200": {"description": "Durable acceptance receipt or safe current job status.", "content": {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"type": "object", "additionalProperties": false, "required": ["id", "accepted"], "properties": {"id": {"type": "string"}, "accepted": {"const": true}}}}}}}}, "400": {"description": "Invalid request; only empty JSON bodies accepted."}, "403": {"description": "Missing current specialty/contact-read authority or unsupported record restriction."}, "404": {"description": "Contact or same-owner job unavailable."}, "409": {"description": "Changed lifecycle, receipt conflict, or running job lease not expired."}, "429": {"description": "Rate limit exceeded."}}
  /api/v1/conversations/{id}/inbox-state:
    get:
      x-seedly-oauth-scope: "conversations:read"
      x-seedly-standard-scope: "conversations:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getInboxState"
      tags: ["Conversations"]
      summary: "getInboxState"
      description: "Explicit location-wide OAuth/Standard v2 route approval plus contacts:read is required. Legacy and restricted record grants are unsupported. Live tenant/contact/company parents are rechecked; write retries retain their original relationship binding. Existing approvals do not automatically gain these operations. Inbox state is shared CRM metadata, including on Gmail conversations; it grants no access to private message bodies. Read/unread updates only the inbox badge, not message/provider read receipts. Marking unread preserves any existing positive count. Snoozing uses epoch milliseconds, future and at most365days; null unsnoozes and opens the thread. Tags are conversation-local labels, not contact tag definitions; case-insensitive writes inspect at most500existing tags."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe projection or minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","isRead","unreadCount","isArchived","isStarred","status","snoozedUntil"],"properties":{"id":{"type":"string"},"isRead":{"type":"boolean"},"unreadCount":{"type":"number"},"isArchived":{"type":"boolean"},"isStarred":{"type":"boolean"},"status":{"enum":["open","closed","snoozed"]},"snoozedUntil":{"type":["number","null"]}}}}}}}},"400":{"description":"Invalid input, cursor or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current route/source permission or live parent."},"409":{"description":"Idempotency conflict, including changed parent relationship."},"429":{"description":"Rate limit exceeded."}}
    patch:
      x-seedly-oauth-scope: "conversations:write"
      x-seedly-standard-scope: "conversations:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "updateInboxState"
      tags: ["Conversations"]
      summary: "updateInboxState"
      description: "Explicit location-wide OAuth/Standard v2 route approval plus contacts:read is required. Legacy and restricted record grants are unsupported. Live tenant/contact/company parents are rechecked; write retries retain their original relationship binding. Existing approvals do not automatically gain these operations. Inbox state is shared CRM metadata, including on Gmail conversations; it grants no access to private message bodies. Read/unread updates only the inbox badge, not message/provider read receipts. Marking unread preserves any existing positive count. Snoozing uses epoch milliseconds, future and at most365days; null unsnoozes and opens the thread. Tags are conversation-local labels, not contact tag definitions; case-insensitive writes inspect at most500existing tags."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe projection or minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"const":true}}}}}}}},"400":{"description":"Invalid input, cursor or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current route/source permission or live parent."},"409":{"description":"Idempotency conflict, including changed parent relationship."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"minProperties":1,"properties":{"isRead":{"type":"boolean"},"isArchived":{"type":"boolean"},"isStarred":{"type":"boolean"},"snoozedUntil":{"type":["integer","null"]}}}}}}
  /api/v1/conversations/{id}/tags:
    get:
      x-seedly-oauth-scope: "conversations:read"
      x-seedly-standard-scope: "conversations:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "listInboxTags"
      tags: ["Conversations"]
      summary: "listInboxTags"
      description: "Explicit location-wide OAuth/Standard v2 route approval plus contacts:read is required. Legacy and restricted record grants are unsupported. Live tenant/contact/company parents are rechecked; write retries retain their original relationship binding. Existing approvals do not automatically gain these operations. Inbox state is shared CRM metadata, including on Gmail conversations; it grants no access to private message bodies. Read/unread updates only the inbox badge, not message/provider read receipts. Marking unread preserves any existing positive count. Snoozing uses epoch milliseconds, future and at most365days; null unsnoozes and opens the thread. Tags are conversation-local labels, not contact tag definitions; case-insensitive writes inspect at most500existing tags."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":8192}}]
      responses: {"200":{"description":"Safe projection or minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","tag"],"properties":{"id":{"type":"string"},"tag":{"type":"string"}}}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Invalid input, cursor or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current route/source permission or live parent."},"409":{"description":"Idempotency conflict, including changed parent relationship."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/conversations/{id}/tags/add:
    post:
      x-seedly-oauth-scope: "conversations:write"
      x-seedly-standard-scope: "conversations:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "addInboxTag"
      tags: ["Conversations"]
      summary: "addInboxTag"
      description: "Explicit location-wide OAuth/Standard v2 route approval plus contacts:read is required. Legacy and restricted record grants are unsupported. Live tenant/contact/company parents are rechecked; write retries retain their original relationship binding. Existing approvals do not automatically gain these operations. Inbox state is shared CRM metadata, including on Gmail conversations; it grants no access to private message bodies. Read/unread updates only the inbox badge, not message/provider read receipts. Marking unread preserves any existing positive count. Snoozing uses epoch milliseconds, future and at most365days; null unsnoozes and opens the thread. Tags are conversation-local labels, not contact tag definitions; case-insensitive writes inspect at most500existing tags."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe projection or minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"const":true}}}}}}}},"400":{"description":"Invalid input, cursor or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current route/source permission or live parent."},"409":{"description":"Idempotency conflict, including changed parent relationship."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["tag"],"properties":{"tag":{"type":"string","minLength":1,"maxLength":100}}}}}}
  /api/v1/conversations/{id}/tags/remove:
    post:
      x-seedly-oauth-scope: "conversations:write"
      x-seedly-standard-scope: "conversations:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "removeInboxTag"
      tags: ["Conversations"]
      summary: "removeInboxTag"
      description: "Explicit location-wide OAuth/Standard v2 route approval plus contacts:read is required. Legacy and restricted record grants are unsupported. Live tenant/contact/company parents are rechecked; write retries retain their original relationship binding. Existing approvals do not automatically gain these operations. Inbox state is shared CRM metadata, including on Gmail conversations; it grants no access to private message bodies. Read/unread updates only the inbox badge, not message/provider read receipts. Marking unread preserves any existing positive count. Snoozing uses epoch milliseconds, future and at most365days; null unsnoozes and opens the thread. Tags are conversation-local labels, not contact tag definitions; case-insensitive writes inspect at most500existing tags."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe projection or minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"const":true}}}}}}}},"400":{"description":"Invalid input, cursor or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current route/source permission or live parent."},"409":{"description":"Idempotency conflict, including changed parent relationship."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["tag"],"properties":{"tag":{"type":"string","minLength":1,"maxLength":100}}}}}}
  /api/v1/conversation-messages/search:
    get:
      x-seedly-oauth-scope: "conversations:read"
      x-seedly-standard-scope: "conversations:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "searchSharedMessages"
      tags: ["Conversations"]
      summary: "searchSharedMessages"
      description: "Explicit location-wide OAuth/Standard v2 route approval plus contacts:read is required. Legacy and restricted record grants are unsupported. Live tenant/contact/company parents are rechecked; write retries retain their original relationship binding. Existing approvals do not automatically gain these operations. Search requires one shared channel. Gmail is excluded in the search index before matching/pagination, so private messages cannot affect cursors or hits. Returns plain-text snippets up to2000 characters and no subject, headers, attachments, provider or mailbox data. Follow cursor even for empty filtered pages."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":8192}},{"name":"search","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":200}},{"name":"channel","in":"query","required":true,"schema":{"type":"string","enum":["sms","email","email-transactional","messenger","instagram","social_dm","live_chat"]}}]
      responses: {"200":{"description":"Safe projection or minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","conversationId","contactId","channel","direction","bodyText","createdAt"],"properties":{"id":{"type":"string"},"conversationId":{"type":"string"},"contactId":{"type":"string"},"channel":{"type":"string"},"direction":{"enum":["inbound","outbound"]},"bodyText":{"type":"string","maxLength":2000},"createdAt":{"type":"number"}}}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Invalid input, cursor or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current route/source permission or live parent."},"409":{"description":"Idempotency conflict, including changed parent relationship."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/contacts/deleted:
    get:
      x-seedly-oauth-scope: "contacts:read"
      x-seedly-standard-scope: "contacts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listContactDeleted
      tags: [Contacts]
      summary: Discover contact deleted
      description: Fresh location-wide contacts:read only. Legacy keys and restricted grants are denied. Follow every cursor, including after empty pages. Duplicates match exact email or phone, or case-insensitive first and last name. No hidden metadata or provider identifiers are returned.
      parameters: [{"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 50, "default": 25}}, {"name": "cursor", "in": "query", "schema": {"type": "string", "maxLength": 16384}}]
      responses: {"200": {"description": "Safe summaries. Empty pages may still have a continuation cursor.", "content": {"application/json": {"schema": {"type": "object", "required": ["data", "meta"], "properties": {"data": {"type": "array", "items": {"type": "object", "additionalProperties": false, "required": ["id", "firstName", "lastName", "email", "phone", "company", "deletedAt", "daysUntilPermanentDeletion"], "properties": {"id": {"type": "string"}, "firstName": {"type": "string"}, "lastName": {"type": "string"}, "email": {"type": ["string", "null"]}, "phone": {"type": ["string", "null"]}, "company": {"type": ["string", "null"]}, "deletedAt": {"type": "string", "format": "date-time"}, "daysUntilPermanentDeletion": {"type": "integer", "minimum": 0}}}}, "meta": {"$ref": "#/components/schemas/ProfileReadPage"}}}}}}, "400": {"description": "Invalid cursor or query."}, "403": {"description": "Missing fresh location-wide operation approval."}, "404": {"description": "Source contact not found."}, "429": {"description": "Rate limit exceeded."}}
  /api/v1/contacts/{id}/duplicates:
    get:
      x-seedly-oauth-scope: "contacts:read"
      x-seedly-standard-scope: "contacts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listContactDuplicates
      tags: [Contacts]
      summary: Discover contact duplicates
      description: Fresh location-wide contacts:read only. Legacy keys and restricted grants are denied. Follow every cursor, including after empty pages. Duplicates match exact email or phone, or case-insensitive first and last name. No hidden metadata or provider identifiers are returned.
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 50, "default": 25}}, {"name": "cursor", "in": "query", "schema": {"type": "string", "maxLength": 16384}}]
      responses: {"200": {"description": "Safe summaries. Empty pages may still have a continuation cursor.", "content": {"application/json": {"schema": {"type": "object", "required": ["data", "meta"], "properties": {"data": {"type": "array", "items": {"type": "object", "additionalProperties": false, "required": ["id", "firstName", "lastName", "email", "phone", "company", "matchReasons"], "properties": {"id": {"type": "string"}, "firstName": {"type": "string"}, "lastName": {"type": "string"}, "email": {"type": ["string", "null"]}, "phone": {"type": ["string", "null"]}, "company": {"type": ["string", "null"]}, "matchReasons": {"type": "array", "items": {"type": "string", "enum": ["email", "phone", "name"]}}}}}, "meta": {"$ref": "#/components/schemas/ProfileReadPage"}}}}}}, "400": {"description": "Invalid cursor or query."}, "403": {"description": "Missing fresh location-wide operation approval."}, "404": {"description": "Source contact not found."}, "429": {"description": "Rate limit exceeded."}}
  /api/v1/calendars/catalog:
    get:
      x-seedly-oauth-scope: "calendars:read"
      x-seedly-standard-scope: "calendars:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "listCalendarCatalog"
      tags: ["Calendars"]
      summary: "listCalendarCatalog"
      description: "Bounded insertion-descending collection for explicitly approved location-wide OAuth and Standard v2 grants. Default 25, maximum 50. Follow the opaque cursor even when a filtered page is empty. Legacy keys and restricted record grants are unsupported. Existing Standard route approvals do not automatically gain this operation. Returns active and inactive profiles for the same calendar resource IDs used by configuration routes. Provider secrets and settings are excluded. Existing /calendars remains the compatibility published catalog."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":8192}}]
      responses: {"200":{"description":"Bounded page.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","name","description","slug","timezone","type","isActive","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"slug":{"type":"string"},"timezone":{"type":"string"},"type":{"type":"string"},"isActive":{"type":"boolean"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Invalid pagination."},"401":{"description":"Invalid credential."},"403":{"description":"Missing or stale permission."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/appointments:
    get:
      x-seedly-oauth-scope: "appointments:read"
      x-seedly-standard-scope: "appointments:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "listAppointmentRecords"
      tags: ["Calendars"]
      summary: "listAppointmentRecords"
      description: "Bounded insertion-descending collection for explicitly approved location-wide OAuth and Standard v2 grants. Default 25, maximum 50. Follow the opaque cursor even when a filtered page is empty. Legacy keys and restricted record grants are unsupported. Existing Standard route approvals do not automatically gain this operation. Also requires contacts:read. Missing, foreign or deleted related contacts and foreign or missing calendars/types are excluded. No embedded contact details, notes or booking tokens. Existing /calendars/appointments remains unchanged."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":8192}}]
      responses: {"200":{"description":"Bounded page.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","calendarId","appointmentTypeId","contactId","title","startTime","endTime","status","createdAt"],"properties":{"id":{"type":"string"},"calendarId":{"type":"string"},"appointmentTypeId":{"type":["string","null"]},"contactId":{"type":["string","null"]},"title":{"type":["string","null"]},"startTime":{"type":"string"},"endTime":{"type":"string"},"status":{"type":"string"},"createdAt":{"type":"string"}}}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Invalid pagination."},"401":{"description":"Invalid credential."},"403":{"description":"Missing or stale permission."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/custom-field-schemas:
    get:
      x-seedly-oauth-scope: "custom-fields:read"
      x-seedly-standard-scope: "custom-fields:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "fieldSchemaGetCustomFieldSchemas"
      summary: "GET /api/v1/custom-field-schemas"
      tags: ["Contacts"]
      description: "Explicit new location-wide Standard v2/OAuth approval; legacy and restricted grants denied. Native contact update/view permission is required for contact definitions/folders; opportunity definitions additionally check current all-record deals update/view permission without altering existing scope fingerprints. Historical stored values are never migrated by rename/type edits. Deletion deactivates definitions; restore reactivates the same ID. Replays recheck authorization and tenant-bound target. Folder deletion moves direct fields and child folders to root atomically, maximum 1000 combined children; larger existing folders remain manageable through unchanged native cleanup. Maximum JSON body 256 KiB. API creation and schema-wide checks support at most 1000 definitions; reactivation at capacity is allowed. Native operations are not subject to these integration-only count limits. Reads use insertion-order cursor pagination; ordinary metadata updates remain available on larger historical collections. File/signature definitions do not grant upload or value access."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"includeInactive","in":"query","schema":{"type":"boolean","default":false}}]
      responses: {"200":{"description":"Definition projection, paginated directory or minimal mutation receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"name":{"type":"string"},"label":{"type":"string"},"fieldType":{"type":"string"},"options":{"type":"array","items":{"type":"string"}},"isRequired":{"type":"boolean"},"sortOrder":{"type":"number"},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"group":{"type":["string","null"]},"validationRegex":{"type":["string","null"]},"dependsOnFieldId":{"type":["string","null"]},"folderId":{"type":["string","null"]}},"required":["id","name","label","fieldType","options","isRequired","sortOrder","isActive","createdAt","updatedAt"]}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Invalid schema, dependency cycle, input, cursor or operation size limit."},"403":{"description":"Missing or stale approval, restricted grant or native permission denied."},"404":{"description":"Target unavailable."},"409":{"description":"Idempotency conflict."},"429":{"description":"Rate limited."}}
    post:
      x-seedly-oauth-scope: "custom-fields:write"
      x-seedly-standard-scope: "custom-fields:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "fieldSchemaPostCustomFieldSchemas"
      summary: "POST /api/v1/custom-field-schemas"
      tags: ["Contacts"]
      description: "Explicit new location-wide Standard v2/OAuth approval; legacy and restricted grants denied. Native contact update/view permission is required for contact definitions/folders; opportunity definitions additionally check current all-record deals update/view permission without altering existing scope fingerprints. Historical stored values are never migrated by rename/type edits. Deletion deactivates definitions; restore reactivates the same ID. Replays recheck authorization and tenant-bound target. Folder deletion moves direct fields and child folders to root atomically, maximum 1000 combined children; larger existing folders remain manageable through unchanged native cleanup. Maximum JSON body 256 KiB. API creation and schema-wide checks support at most 1000 definitions; reactivation at capacity is allowed. Native operations are not subject to these integration-only count limits. Reads use insertion-order cursor pagination; ordinary metadata updates remain available on larger historical collections. File/signature definitions do not grant upload or value access."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Definition projection, paginated directory or minimal mutation receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","created"],"properties":{"id":{"type":"string"},"created":{"const":true}}}}}}}},"400":{"description":"Invalid schema, dependency cycle, input, cursor or operation size limit."},"403":{"description":"Missing or stale approval, restricted grant or native permission denied."},"404":{"description":"Target unavailable."},"409":{"description":"Idempotency conflict."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":100},"label":{"type":"string","minLength":1,"maxLength":255},"fieldType":{"type":"string","enum":["text","number","date","select","boolean","url","email","phone","monetary","file","signature","radio","textbox_list"]},"options":{"type":"array","maxItems":200,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":500}},"isRequired":{"type":"boolean"},"sortOrder":{"type":"number","minimum":-1000000000.0,"maximum":1000000000.0},"group":{"type":"string","maxLength":255},"validationRegex":{"type":"string","maxLength":500},"dependsOnFieldId":{"type":["string","null"]},"folderId":{"type":["string","null"]}},"required":["name","label","fieldType"]}}}}
  /api/v1/custom-field-schemas/{id}:
    get:
      x-seedly-oauth-scope: "custom-fields:read"
      x-seedly-standard-scope: "custom-fields:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "fieldSchemaGetCustomFieldSchemas:Id"
      summary: "GET /api/v1/custom-field-schemas/{id}"
      tags: ["Contacts"]
      description: "Explicit new location-wide Standard v2/OAuth approval; legacy and restricted grants denied. Native contact update/view permission is required for contact definitions/folders; opportunity definitions additionally check current all-record deals update/view permission without altering existing scope fingerprints. Historical stored values are never migrated by rename/type edits. Deletion deactivates definitions; restore reactivates the same ID. Replays recheck authorization and tenant-bound target. Folder deletion moves direct fields and child folders to root atomically, maximum 1000 combined children; larger existing folders remain manageable through unchanged native cleanup. Maximum JSON body 256 KiB. API creation and schema-wide checks support at most 1000 definitions; reactivation at capacity is allowed. Native operations are not subject to these integration-only count limits. Reads use insertion-order cursor pagination; ordinary metadata updates remain available on larger historical collections. File/signature definitions do not grant upload or value access."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Definition projection, paginated directory or minimal mutation receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"name":{"type":"string"},"label":{"type":"string"},"fieldType":{"type":"string"},"options":{"type":"array","items":{"type":"string"}},"isRequired":{"type":"boolean"},"sortOrder":{"type":"number"},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"group":{"type":["string","null"]},"validationRegex":{"type":["string","null"]},"dependsOnFieldId":{"type":["string","null"]},"folderId":{"type":["string","null"]}},"required":["id","name","label","fieldType","options","isRequired","sortOrder","isActive","createdAt","updatedAt"]}}}}}},"400":{"description":"Invalid schema, dependency cycle, input, cursor or operation size limit."},"403":{"description":"Missing or stale approval, restricted grant or native permission denied."},"404":{"description":"Target unavailable."},"409":{"description":"Idempotency conflict."},"429":{"description":"Rate limited."}}
    patch:
      x-seedly-oauth-scope: "custom-fields:write"
      x-seedly-standard-scope: "custom-fields:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "fieldSchemaPatchCustomFieldSchemas:Id"
      summary: "PATCH /api/v1/custom-field-schemas/{id}"
      tags: ["Contacts"]
      description: "Explicit new location-wide Standard v2/OAuth approval; legacy and restricted grants denied. Native contact update/view permission is required for contact definitions/folders; opportunity definitions additionally check current all-record deals update/view permission without altering existing scope fingerprints. Historical stored values are never migrated by rename/type edits. Deletion deactivates definitions; restore reactivates the same ID. Replays recheck authorization and tenant-bound target. Folder deletion moves direct fields and child folders to root atomically, maximum 1000 combined children; larger existing folders remain manageable through unchanged native cleanup. Maximum JSON body 256 KiB. API creation and schema-wide checks support at most 1000 definitions; reactivation at capacity is allowed. Native operations are not subject to these integration-only count limits. Reads use insertion-order cursor pagination; ordinary metadata updates remain available on larger historical collections. File/signature definitions do not grant upload or value access."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Definition projection, paginated directory or minimal mutation receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"const":true}}}}}}}},"400":{"description":"Invalid schema, dependency cycle, input, cursor or operation size limit."},"403":{"description":"Missing or stale approval, restricted grant or native permission denied."},"404":{"description":"Target unavailable."},"409":{"description":"Idempotency conflict."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":100},"label":{"type":"string","minLength":1,"maxLength":255},"fieldType":{"type":"string","enum":["text","number","date","select","boolean","url","email","phone","monetary","file","signature","radio","textbox_list"]},"options":{"type":"array","maxItems":200,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":500}},"isRequired":{"type":"boolean"},"sortOrder":{"type":"number","minimum":-1000000000.0,"maximum":1000000000.0},"group":{"type":"string","maxLength":255},"validationRegex":{"type":"string","maxLength":500},"dependsOnFieldId":{"type":["string","null"]},"folderId":{"type":["string","null"]}},"minProperties":1}}}}
    delete:
      x-seedly-oauth-scope: "custom-fields:delete"
      x-seedly-standard-scope: "custom-fields:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "fieldSchemaDeleteCustomFieldSchemas:Id"
      summary: "DELETE /api/v1/custom-field-schemas/{id}"
      tags: ["Contacts"]
      description: "Explicit new location-wide Standard v2/OAuth approval; legacy and restricted grants denied. Native contact update/view permission is required for contact definitions/folders; opportunity definitions additionally check current all-record deals update/view permission without altering existing scope fingerprints. Historical stored values are never migrated by rename/type edits. Deletion deactivates definitions; restore reactivates the same ID. Replays recheck authorization and tenant-bound target. Folder deletion moves direct fields and child folders to root atomically, maximum 1000 combined children; larger existing folders remain manageable through unchanged native cleanup. Maximum JSON body 256 KiB. API creation and schema-wide checks support at most 1000 definitions; reactivation at capacity is allowed. Native operations are not subject to these integration-only count limits. Reads use insertion-order cursor pagination; ordinary metadata updates remain available on larger historical collections. File/signature definitions do not grant upload or value access."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Definition projection, paginated directory or minimal mutation receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","deleted"],"properties":{"id":{"type":"string"},"deleted":{"const":true}}}}}}}},"400":{"description":"Invalid schema, dependency cycle, input, cursor or operation size limit."},"403":{"description":"Missing or stale approval, restricted grant or native permission denied."},"404":{"description":"Target unavailable."},"409":{"description":"Idempotency conflict."},"429":{"description":"Rate limited."}}
  /api/v1/opportunity-custom-fields:
    get:
      x-seedly-oauth-scope: "custom-fields:read"
      x-seedly-standard-scope: "custom-fields:read"
      x-seedly-standard-operation-permissions: [["deals","view"]]
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "fieldSchemaGetOpportunityCustomFields"
      summary: "GET /api/v1/opportunity-custom-fields"
      tags: ["Contacts"]
      description: "Explicit new location-wide Standard v2/OAuth approval; legacy and restricted grants denied. Native contact update/view permission is required for contact definitions/folders; opportunity definitions additionally check current all-record deals update/view permission without altering existing scope fingerprints. Historical stored values are never migrated by rename/type edits. Deletion deactivates definitions; restore reactivates the same ID. Replays recheck authorization and tenant-bound target. Folder deletion moves direct fields and child folders to root atomically, maximum 1000 combined children; larger existing folders remain manageable through unchanged native cleanup. Maximum JSON body 256 KiB. API creation and schema-wide checks support at most 1000 definitions; reactivation at capacity is allowed. Native operations are not subject to these integration-only count limits. Reads use insertion-order cursor pagination; ordinary metadata updates remain available on larger historical collections. File/signature definitions do not grant upload or value access."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"includeInactive","in":"query","schema":{"type":"boolean","default":false}}]
      responses: {"200":{"description":"Definition projection, paginated directory or minimal mutation receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"name":{"type":"string"},"label":{"type":"string"},"fieldType":{"type":"string"},"options":{"type":"array","items":{"type":"string"}},"isRequired":{"type":"boolean"},"sortOrder":{"type":"number"},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","name","label","fieldType","options","isRequired","sortOrder","isActive","createdAt","updatedAt"]}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Invalid schema, dependency cycle, input, cursor or operation size limit."},"403":{"description":"Missing or stale approval, restricted grant or native permission denied."},"404":{"description":"Target unavailable."},"409":{"description":"Idempotency conflict."},"429":{"description":"Rate limited."}}
    post:
      x-seedly-oauth-scope: "custom-fields:write"
      x-seedly-standard-scope: "custom-fields:write"
      x-seedly-standard-operation-permissions: [["deals","update"]]
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "fieldSchemaPostOpportunityCustomFields"
      summary: "POST /api/v1/opportunity-custom-fields"
      tags: ["Contacts"]
      description: "Explicit new location-wide Standard v2/OAuth approval; legacy and restricted grants denied. Native contact update/view permission is required for contact definitions/folders; opportunity definitions additionally check current all-record deals update/view permission without altering existing scope fingerprints. Historical stored values are never migrated by rename/type edits. Deletion deactivates definitions; restore reactivates the same ID. Replays recheck authorization and tenant-bound target. Folder deletion moves direct fields and child folders to root atomically, maximum 1000 combined children; larger existing folders remain manageable through unchanged native cleanup. Maximum JSON body 256 KiB. API creation and schema-wide checks support at most 1000 definitions; reactivation at capacity is allowed. Native operations are not subject to these integration-only count limits. Reads use insertion-order cursor pagination; ordinary metadata updates remain available on larger historical collections. File/signature definitions do not grant upload or value access."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Definition projection, paginated directory or minimal mutation receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","created"],"properties":{"id":{"type":"string"},"created":{"const":true}}}}}}}},"400":{"description":"Invalid schema, dependency cycle, input, cursor or operation size limit."},"403":{"description":"Missing or stale approval, restricted grant or native permission denied."},"404":{"description":"Target unavailable."},"409":{"description":"Idempotency conflict."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":100},"label":{"type":"string","minLength":1,"maxLength":255},"fieldType":{"type":"string","enum":["text","number","date","select","boolean","url","email","phone","monetary","file","signature","radio","textbox_list"]},"options":{"type":"array","maxItems":200,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":500}},"isRequired":{"type":"boolean"},"sortOrder":{"type":"number","minimum":-1000000000.0,"maximum":1000000000.0}},"required":["name","label","fieldType"]}}}}
  /api/v1/opportunity-custom-fields/{id}:
    get:
      x-seedly-oauth-scope: "custom-fields:read"
      x-seedly-standard-scope: "custom-fields:read"
      x-seedly-standard-operation-permissions: [["deals","view"]]
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "fieldSchemaGetOpportunityCustomFields:Id"
      summary: "GET /api/v1/opportunity-custom-fields/{id}"
      tags: ["Contacts"]
      description: "Explicit new location-wide Standard v2/OAuth approval; legacy and restricted grants denied. Native contact update/view permission is required for contact definitions/folders; opportunity definitions additionally check current all-record deals update/view permission without altering existing scope fingerprints. Historical stored values are never migrated by rename/type edits. Deletion deactivates definitions; restore reactivates the same ID. Replays recheck authorization and tenant-bound target. Folder deletion moves direct fields and child folders to root atomically, maximum 1000 combined children; larger existing folders remain manageable through unchanged native cleanup. Maximum JSON body 256 KiB. API creation and schema-wide checks support at most 1000 definitions; reactivation at capacity is allowed. Native operations are not subject to these integration-only count limits. Reads use insertion-order cursor pagination; ordinary metadata updates remain available on larger historical collections. File/signature definitions do not grant upload or value access."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Definition projection, paginated directory or minimal mutation receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"name":{"type":"string"},"label":{"type":"string"},"fieldType":{"type":"string"},"options":{"type":"array","items":{"type":"string"}},"isRequired":{"type":"boolean"},"sortOrder":{"type":"number"},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","name","label","fieldType","options","isRequired","sortOrder","isActive","createdAt","updatedAt"]}}}}}},"400":{"description":"Invalid schema, dependency cycle, input, cursor or operation size limit."},"403":{"description":"Missing or stale approval, restricted grant or native permission denied."},"404":{"description":"Target unavailable."},"409":{"description":"Idempotency conflict."},"429":{"description":"Rate limited."}}
    patch:
      x-seedly-oauth-scope: "custom-fields:write"
      x-seedly-standard-scope: "custom-fields:write"
      x-seedly-standard-operation-permissions: [["deals","update"]]
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "fieldSchemaPatchOpportunityCustomFields:Id"
      summary: "PATCH /api/v1/opportunity-custom-fields/{id}"
      tags: ["Contacts"]
      description: "Explicit new location-wide Standard v2/OAuth approval; legacy and restricted grants denied. Native contact update/view permission is required for contact definitions/folders; opportunity definitions additionally check current all-record deals update/view permission without altering existing scope fingerprints. Historical stored values are never migrated by rename/type edits. Deletion deactivates definitions; restore reactivates the same ID. Replays recheck authorization and tenant-bound target. Folder deletion moves direct fields and child folders to root atomically, maximum 1000 combined children; larger existing folders remain manageable through unchanged native cleanup. Maximum JSON body 256 KiB. API creation and schema-wide checks support at most 1000 definitions; reactivation at capacity is allowed. Native operations are not subject to these integration-only count limits. Reads use insertion-order cursor pagination; ordinary metadata updates remain available on larger historical collections. File/signature definitions do not grant upload or value access."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Definition projection, paginated directory or minimal mutation receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"const":true}}}}}}}},"400":{"description":"Invalid schema, dependency cycle, input, cursor or operation size limit."},"403":{"description":"Missing or stale approval, restricted grant or native permission denied."},"404":{"description":"Target unavailable."},"409":{"description":"Idempotency conflict."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":100},"label":{"type":"string","minLength":1,"maxLength":255},"fieldType":{"type":"string","enum":["text","number","date","select","boolean","url","email","phone","monetary","file","signature","radio","textbox_list"]},"options":{"type":"array","maxItems":200,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":500}},"isRequired":{"type":"boolean"},"sortOrder":{"type":"number","minimum":-1000000000.0,"maximum":1000000000.0}},"minProperties":1}}}}
    delete:
      x-seedly-oauth-scope: "custom-fields:delete"
      x-seedly-standard-scope: "custom-fields:delete"
      x-seedly-standard-operation-permissions: [["deals","update"]]
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "fieldSchemaDeleteOpportunityCustomFields:Id"
      summary: "DELETE /api/v1/opportunity-custom-fields/{id}"
      tags: ["Contacts"]
      description: "Explicit new location-wide Standard v2/OAuth approval; legacy and restricted grants denied. Native contact update/view permission is required for contact definitions/folders; opportunity definitions additionally check current all-record deals update/view permission without altering existing scope fingerprints. Historical stored values are never migrated by rename/type edits. Deletion deactivates definitions; restore reactivates the same ID. Replays recheck authorization and tenant-bound target. Folder deletion moves direct fields and child folders to root atomically, maximum 1000 combined children; larger existing folders remain manageable through unchanged native cleanup. Maximum JSON body 256 KiB. API creation and schema-wide checks support at most 1000 definitions; reactivation at capacity is allowed. Native operations are not subject to these integration-only count limits. Reads use insertion-order cursor pagination; ordinary metadata updates remain available on larger historical collections. File/signature definitions do not grant upload or value access."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Definition projection, paginated directory or minimal mutation receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","deleted"],"properties":{"id":{"type":"string"},"deleted":{"const":true}}}}}}}},"400":{"description":"Invalid schema, dependency cycle, input, cursor or operation size limit."},"403":{"description":"Missing or stale approval, restricted grant or native permission denied."},"404":{"description":"Target unavailable."},"409":{"description":"Idempotency conflict."},"429":{"description":"Rate limited."}}
  /api/v1/custom-field-folder-deletion-jobs:
    post:
      x-seedly-oauth-scope: "custom-fields:delete"
      x-seedly-standard-scope: "custom-fields:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "startCustomFieldFolderDeletionJob"
      tags: ["Contacts"]
      summary: "POST /api/v1/custom-field-folder-deletion-jobs"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Deletes a custom-field folder of any size: contained fields and immediate child folders move to root in batches, then the folder is deleted. Stored record values do not change. Returns a job id. Pauses with children_outside_location if a child belongs to another location, and with target_busy if rows keep moving in."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["folderId"],"properties":{"folderId":{"type":"string"}}}}}}
  /api/v1/custom-field-folder-deletion-jobs/{id}:
    get:
      x-seedly-oauth-scope: "custom-fields:read"
      x-seedly-standard-scope: "custom-fields:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getCustomFieldFolderDeletionJob"
      tags: ["Contacts"]
      summary: "GET /api/v1/custom-field-folder-deletion-jobs/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Reads progress: status, scanned, updated, outsideLocation, failureCode, stalled and partial. Only the credential that started the job can read it."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/custom-field-folder-deletion-jobs/{id}/cancel:
    post:
      x-seedly-oauth-scope: "custom-fields:delete"
      x-seedly-standard-scope: "custom-fields:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "cancelCustomFieldFolderDeletionJob"
      tags: ["Contacts"]
      summary: "POST /api/v1/custom-field-folder-deletion-jobs/{id}/cancel"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Stops later batches. Finished batches are not rolled back, and the job then reports partial. A cancelled job cannot resume."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}
  /api/v1/custom-field-folder-deletion-jobs/{id}/resume:
    post:
      x-seedly-oauth-scope: "custom-fields:delete"
      x-seedly-standard-scope: "custom-fields:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "resumeCustomFieldFolderDeletionJob"
      tags: ["Contacts"]
      summary: "POST /api/v1/custom-field-folder-deletion-jobs/{id}/resume"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Restarts a paused or stalled job from the first row with the current token ceiling. Only the credential that started the job can resume it, within 24 hours of its last update and 72 hours of its start."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}
  /api/v1/custom-field-reorder-jobs:
    post:
      x-seedly-oauth-scope: "custom-fields:write"
      x-seedly-standard-scope: "custom-fields:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "startCustomFieldReorderJob"
      tags: ["Contacts"]
      summary: "POST /api/v1/custom-field-reorder-jobs"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Moves one field definition one place up or down among the active fields in its folder, for locations above the 1000 definition limit of the reorder route. Domain contact needs contacts update, domain deal needs deals update. Nothing changes until the final batch, which swaps both positions at once. At the end of the list the job completes with updated 0."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["domain","fieldId","direction"],"properties":{"domain":{"type":"string","enum":["contact","deal"]},"fieldId":{"type":"string"},"direction":{"type":"string","enum":["up","down"]}}}}}}
  /api/v1/custom-field-reorder-jobs/{id}:
    get:
      x-seedly-oauth-scope: "custom-fields:read"
      x-seedly-standard-scope: "custom-fields:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getCustomFieldReorderJob"
      tags: ["Contacts"]
      summary: "GET /api/v1/custom-field-reorder-jobs/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Reads progress: status, scanned, updated, outsideLocation, failureCode, stalled and partial. Only the credential that started the job can read it."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/custom-field-reorder-jobs/{id}/cancel:
    post:
      x-seedly-oauth-scope: "custom-fields:write"
      x-seedly-standard-scope: "custom-fields:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "cancelCustomFieldReorderJob"
      tags: ["Contacts"]
      summary: "POST /api/v1/custom-field-reorder-jobs/{id}/cancel"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Stops later batches. Finished batches are not rolled back, and the job then reports partial. A cancelled job cannot resume."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}
  /api/v1/custom-field-reorder-jobs/{id}/resume:
    post:
      x-seedly-oauth-scope: "custom-fields:write"
      x-seedly-standard-scope: "custom-fields:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "resumeCustomFieldReorderJob"
      tags: ["Contacts"]
      summary: "POST /api/v1/custom-field-reorder-jobs/{id}/resume"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Restarts a paused or stalled job from the first row with the current token ceiling. Only the credential that started the job can resume it, within 24 hours of its last update and 72 hours of its start."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}
  /api/v1/custom-field-folders:
    get:
      x-seedly-oauth-scope: "custom-fields:read"
      x-seedly-standard-scope: "custom-fields:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "fieldSchemaGetCustomFieldFolders"
      summary: "GET /api/v1/custom-field-folders"
      tags: ["Contacts"]
      description: "Explicit new location-wide Standard v2/OAuth approval; legacy and restricted grants denied. Native contact update/view permission is required for contact definitions/folders; opportunity definitions additionally check current all-record deals update/view permission without altering existing scope fingerprints. Historical stored values are never migrated by rename/type edits. Deletion deactivates definitions; restore reactivates the same ID. Replays recheck authorization and tenant-bound target. Folder deletion moves direct fields and child folders to root atomically, maximum 1000 combined children; larger existing folders remain manageable through unchanged native cleanup. Maximum JSON body 256 KiB. API creation and schema-wide checks support at most 1000 definitions; reactivation at capacity is allowed. Native operations are not subject to these integration-only count limits. Reads use insertion-order cursor pagination; ordinary metadata updates remain available on larger historical collections. File/signature definitions do not grant upload or value access."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"includeInactive","in":"query","schema":{"type":"boolean","default":false}}]
      responses: {"200":{"description":"Definition projection, paginated directory or minimal mutation receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"name":{"type":"string"},"parentId":{"type":["string","null"]},"sortOrder":{"type":"number"}},"required":["id","name","parentId","sortOrder"]}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Invalid schema, dependency cycle, input, cursor or operation size limit."},"403":{"description":"Missing or stale approval, restricted grant or native permission denied."},"404":{"description":"Target unavailable."},"409":{"description":"Idempotency conflict."},"429":{"description":"Rate limited."}}
    post:
      x-seedly-oauth-scope: "custom-fields:write"
      x-seedly-standard-scope: "custom-fields:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "fieldSchemaPostCustomFieldFolders"
      summary: "POST /api/v1/custom-field-folders"
      tags: ["Contacts"]
      description: "Explicit new location-wide Standard v2/OAuth approval; legacy and restricted grants denied. Native contact update/view permission is required for contact definitions/folders; opportunity definitions additionally check current all-record deals update/view permission without altering existing scope fingerprints. Historical stored values are never migrated by rename/type edits. Deletion deactivates definitions; restore reactivates the same ID. Replays recheck authorization and tenant-bound target. Folder deletion moves direct fields and child folders to root atomically, maximum 1000 combined children; larger existing folders remain manageable through unchanged native cleanup. Maximum JSON body 256 KiB. API creation and schema-wide checks support at most 1000 definitions; reactivation at capacity is allowed. Native operations are not subject to these integration-only count limits. Reads use insertion-order cursor pagination; ordinary metadata updates remain available on larger historical collections. File/signature definitions do not grant upload or value access."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Definition projection, paginated directory or minimal mutation receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","created"],"properties":{"id":{"type":"string"},"created":{"const":true}}}}}}}},"400":{"description":"Invalid schema, dependency cycle, input, cursor or operation size limit."},"403":{"description":"Missing or stale approval, restricted grant or native permission denied."},"404":{"description":"Target unavailable."},"409":{"description":"Idempotency conflict."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":255},"parentId":{"type":"string"}},"required":["name"]}}}}
  /api/v1/custom-field-folders/{id}:
    get:
      x-seedly-oauth-scope: "custom-fields:read"
      x-seedly-standard-scope: "custom-fields:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "fieldSchemaGetCustomFieldFolders:Id"
      summary: "GET /api/v1/custom-field-folders/{id}"
      tags: ["Contacts"]
      description: "Explicit new location-wide Standard v2/OAuth approval; legacy and restricted grants denied. Native contact update/view permission is required for contact definitions/folders; opportunity definitions additionally check current all-record deals update/view permission without altering existing scope fingerprints. Historical stored values are never migrated by rename/type edits. Deletion deactivates definitions; restore reactivates the same ID. Replays recheck authorization and tenant-bound target. Folder deletion moves direct fields and child folders to root atomically, maximum 1000 combined children; larger existing folders remain manageable through unchanged native cleanup. Maximum JSON body 256 KiB. API creation and schema-wide checks support at most 1000 definitions; reactivation at capacity is allowed. Native operations are not subject to these integration-only count limits. Reads use insertion-order cursor pagination; ordinary metadata updates remain available on larger historical collections. File/signature definitions do not grant upload or value access."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Definition projection, paginated directory or minimal mutation receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"name":{"type":"string"},"parentId":{"type":["string","null"]},"sortOrder":{"type":"number"}},"required":["id","name","parentId","sortOrder"]}}}}}},"400":{"description":"Invalid schema, dependency cycle, input, cursor or operation size limit."},"403":{"description":"Missing or stale approval, restricted grant or native permission denied."},"404":{"description":"Target unavailable."},"409":{"description":"Idempotency conflict."},"429":{"description":"Rate limited."}}
    patch:
      x-seedly-oauth-scope: "custom-fields:write"
      x-seedly-standard-scope: "custom-fields:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "fieldSchemaPatchCustomFieldFolders:Id"
      summary: "PATCH /api/v1/custom-field-folders/{id}"
      tags: ["Contacts"]
      description: "Explicit new location-wide Standard v2/OAuth approval; legacy and restricted grants denied. Native contact update/view permission is required for contact definitions/folders; opportunity definitions additionally check current all-record deals update/view permission without altering existing scope fingerprints. Historical stored values are never migrated by rename/type edits. Deletion deactivates definitions; restore reactivates the same ID. Replays recheck authorization and tenant-bound target. Folder deletion moves direct fields and child folders to root atomically, maximum 1000 combined children; larger existing folders remain manageable through unchanged native cleanup. Maximum JSON body 256 KiB. API creation and schema-wide checks support at most 1000 definitions; reactivation at capacity is allowed. Native operations are not subject to these integration-only count limits. Reads use insertion-order cursor pagination; ordinary metadata updates remain available on larger historical collections. File/signature definitions do not grant upload or value access."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Definition projection, paginated directory or minimal mutation receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"const":true}}}}}}}},"400":{"description":"Invalid schema, dependency cycle, input, cursor or operation size limit."},"403":{"description":"Missing or stale approval, restricted grant or native permission denied."},"404":{"description":"Target unavailable."},"409":{"description":"Idempotency conflict."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":255}},"minProperties":1}}}}
    delete:
      x-seedly-oauth-scope: "custom-fields:delete"
      x-seedly-standard-scope: "custom-fields:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "fieldSchemaDeleteCustomFieldFolders:Id"
      summary: "DELETE /api/v1/custom-field-folders/{id}"
      tags: ["Contacts"]
      description: "Explicit new location-wide Standard v2/OAuth approval; legacy and restricted grants denied. Native contact update/view permission is required for contact definitions/folders; opportunity definitions additionally check current all-record deals update/view permission without altering existing scope fingerprints. Historical stored values are never migrated by rename/type edits. Deletion deactivates definitions; restore reactivates the same ID. Replays recheck authorization and tenant-bound target. Folder deletion moves direct fields and child folders to root atomically, maximum 1000 combined children; larger existing folders remain manageable through unchanged native cleanup. Maximum JSON body 256 KiB. API creation and schema-wide checks support at most 1000 definitions; reactivation at capacity is allowed. Native operations are not subject to these integration-only count limits. Reads use insertion-order cursor pagination; ordinary metadata updates remain available on larger historical collections. File/signature definitions do not grant upload or value access."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Definition projection, paginated directory or minimal mutation receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","deleted"],"properties":{"id":{"type":"string"},"deleted":{"const":true}}}}}}}},"400":{"description":"Invalid schema, dependency cycle, input, cursor or operation size limit."},"403":{"description":"Missing or stale approval, restricted grant or native permission denied."},"404":{"description":"Target unavailable."},"409":{"description":"Idempotency conflict."},"429":{"description":"Rate limited."}}
  /api/v1/custom-field-schemas/{id}/restore:
    post:
      x-seedly-oauth-scope: "custom-fields:write"
      x-seedly-standard-scope: "custom-fields:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "fieldSchemaPostCustomFieldSchemas:IdRestore"
      summary: "POST /api/v1/custom-field-schemas/{id}/restore"
      tags: ["Contacts"]
      description: "Explicit new location-wide Standard v2/OAuth approval; legacy and restricted grants denied. Native contact update/view permission is required for contact definitions/folders; opportunity definitions additionally check current all-record deals update/view permission without altering existing scope fingerprints. Historical stored values are never migrated by rename/type edits. Deletion deactivates definitions; restore reactivates the same ID. Replays recheck authorization and tenant-bound target. Folder deletion moves direct fields and child folders to root atomically, maximum 1000 combined children; larger existing folders remain manageable through unchanged native cleanup. Maximum JSON body 256 KiB. API creation and schema-wide checks support at most 1000 definitions; reactivation at capacity is allowed. Native operations are not subject to these integration-only count limits. Reads use insertion-order cursor pagination; ordinary metadata updates remain available on larger historical collections. File/signature definitions do not grant upload or value access."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Definition projection, paginated directory or minimal mutation receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"const":true}}}}}}}},"400":{"description":"Invalid schema, dependency cycle, input, cursor or operation size limit."},"403":{"description":"Missing or stale approval, restricted grant or native permission denied."},"404":{"description":"Target unavailable."},"409":{"description":"Idempotency conflict."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/custom-field-schemas/{id}/reorder:
    post:
      x-seedly-oauth-scope: "custom-fields:write"
      x-seedly-standard-scope: "custom-fields:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "fieldSchemaPostCustomFieldSchemas:IdReorder"
      summary: "POST /api/v1/custom-field-schemas/{id}/reorder"
      tags: ["Contacts"]
      description: "Explicit new location-wide Standard v2/OAuth approval; legacy and restricted grants denied. Native contact update/view permission is required for contact definitions/folders; opportunity definitions additionally check current all-record deals update/view permission without altering existing scope fingerprints. Historical stored values are never migrated by rename/type edits. Deletion deactivates definitions; restore reactivates the same ID. Replays recheck authorization and tenant-bound target. Folder deletion moves direct fields and child folders to root atomically, maximum 1000 combined children; larger existing folders remain manageable through unchanged native cleanup. Maximum JSON body 256 KiB. API creation and schema-wide checks support at most 1000 definitions; reactivation at capacity is allowed. Native operations are not subject to these integration-only count limits. Reads use insertion-order cursor pagination; ordinary metadata updates remain available on larger historical collections. File/signature definitions do not grant upload or value access."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Definition projection, paginated directory or minimal mutation receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"const":true}}}}}}}},"400":{"description":"Invalid schema, dependency cycle, input, cursor or operation size limit."},"403":{"description":"Missing or stale approval, restricted grant or native permission denied."},"404":{"description":"Target unavailable."},"409":{"description":"Idempotency conflict."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"direction":{"type":"string","enum":["up","down"]}},"minProperties":1}}}}
  /api/v1/custom-field-schemas/{id}/folder:
    patch:
      x-seedly-oauth-scope: "custom-fields:write"
      x-seedly-standard-scope: "custom-fields:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "fieldSchemaPatchCustomFieldSchemas:IdFolder"
      summary: "PATCH /api/v1/custom-field-schemas/{id}/folder"
      tags: ["Contacts"]
      description: "Explicit new location-wide Standard v2/OAuth approval; legacy and restricted grants denied. Native contact update/view permission is required for contact definitions/folders; opportunity definitions additionally check current all-record deals update/view permission without altering existing scope fingerprints. Historical stored values are never migrated by rename/type edits. Deletion deactivates definitions; restore reactivates the same ID. Replays recheck authorization and tenant-bound target. Folder deletion moves direct fields and child folders to root atomically, maximum 1000 combined children; larger existing folders remain manageable through unchanged native cleanup. Maximum JSON body 256 KiB. API creation and schema-wide checks support at most 1000 definitions; reactivation at capacity is allowed. Native operations are not subject to these integration-only count limits. Reads use insertion-order cursor pagination; ordinary metadata updates remain available on larger historical collections. File/signature definitions do not grant upload or value access."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Definition projection, paginated directory or minimal mutation receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"const":true}}}}}}}},"400":{"description":"Invalid schema, dependency cycle, input, cursor or operation size limit."},"403":{"description":"Missing or stale approval, restricted grant or native permission denied."},"404":{"description":"Target unavailable."},"409":{"description":"Idempotency conflict."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"folderId":{"type":["string","null"]}},"minProperties":1}}}}
  /api/v1/opportunity-custom-fields/{id}/restore:
    post:
      x-seedly-oauth-scope: "custom-fields:write"
      x-seedly-standard-scope: "custom-fields:write"
      x-seedly-standard-operation-permissions: [["deals","update"]]
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "fieldSchemaPostOpportunityCustomFields:IdRestore"
      summary: "POST /api/v1/opportunity-custom-fields/{id}/restore"
      tags: ["Contacts"]
      description: "Explicit new location-wide Standard v2/OAuth approval; legacy and restricted grants denied. Native contact update/view permission is required for contact definitions/folders; opportunity definitions additionally check current all-record deals update/view permission without altering existing scope fingerprints. Historical stored values are never migrated by rename/type edits. Deletion deactivates definitions; restore reactivates the same ID. Replays recheck authorization and tenant-bound target. Folder deletion moves direct fields and child folders to root atomically, maximum 1000 combined children; larger existing folders remain manageable through unchanged native cleanup. Maximum JSON body 256 KiB. API creation and schema-wide checks support at most 1000 definitions; reactivation at capacity is allowed. Native operations are not subject to these integration-only count limits. Reads use insertion-order cursor pagination; ordinary metadata updates remain available on larger historical collections. File/signature definitions do not grant upload or value access."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Definition projection, paginated directory or minimal mutation receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"const":true}}}}}}}},"400":{"description":"Invalid schema, dependency cycle, input, cursor or operation size limit."},"403":{"description":"Missing or stale approval, restricted grant or native permission denied."},"404":{"description":"Target unavailable."},"409":{"description":"Idempotency conflict."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/opportunity-custom-fields/{id}/reorder:
    post:
      x-seedly-oauth-scope: "custom-fields:write"
      x-seedly-standard-scope: "custom-fields:write"
      x-seedly-standard-operation-permissions: [["deals","update"]]
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "fieldSchemaPostOpportunityCustomFields:IdReorder"
      summary: "POST /api/v1/opportunity-custom-fields/{id}/reorder"
      tags: ["Contacts"]
      description: "Explicit new location-wide Standard v2/OAuth approval; legacy and restricted grants denied. Native contact update/view permission is required for contact definitions/folders; opportunity definitions additionally check current all-record deals update/view permission without altering existing scope fingerprints. Historical stored values are never migrated by rename/type edits. Deletion deactivates definitions; restore reactivates the same ID. Replays recheck authorization and tenant-bound target. Folder deletion moves direct fields and child folders to root atomically, maximum 1000 combined children; larger existing folders remain manageable through unchanged native cleanup. Maximum JSON body 256 KiB. API creation and schema-wide checks support at most 1000 definitions; reactivation at capacity is allowed. Native operations are not subject to these integration-only count limits. Reads use insertion-order cursor pagination; ordinary metadata updates remain available on larger historical collections. File/signature definitions do not grant upload or value access."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Definition projection, paginated directory or minimal mutation receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"const":true}}}}}}}},"400":{"description":"Invalid schema, dependency cycle, input, cursor or operation size limit."},"403":{"description":"Missing or stale approval, restricted grant or native permission denied."},"404":{"description":"Target unavailable."},"409":{"description":"Idempotency conflict."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"direction":{"type":"string","enum":["up","down"]}},"minProperties":1}}}}
  /api/v1/contact-list-definitions:
    get:
      x-seedly-oauth-scope: "contact-lists:read"
      x-seedly-standard-scope: "contact-lists:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getContactListDefinitions"
      tags: ["Audiences"]
      summary: "GET /api/v1/contact-list-definitions"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter reads, writes, count refresh, audience pages and retries recheck contacts:read and each source domain: dealStage requires opportunities:read; email/link/last-contact predicates require conversations:read; booking predicates require appointments:read; form predicates require approved forms submission reads when available. Unsupported/private predicates fail closed. Default 25, maximum 50 records. Follow cursor even when filtered data is empty.  A row whose rule this caller may not read is kept with filterRedacted true, and with filterCriteria null. filterRedactedReason is hidden_pipeline for a deal stage rule when an OAuth user cannot see every pipeline, or unsupported_filter for a stored rule the API cannot validate. That record cannot be read, used or changed individually, so an unsupported rule is fixed in the app. Every other row has filterRedacted false and filterRedactedReason null. A missing scope on a rule the API can read still refuses the page."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":8192}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ContactListDefinition"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or source-domain approval."},"409":{"description":"Idempotency key conflict."},"429":{"description":"Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "contact-lists:write"
      x-seedly-standard-scope: "contact-lists:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postContactListDefinitions"
      tags: ["Audiences"]
      summary: "POST /api/v1/contact-list-definitions"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter reads, writes, count refresh, audience pages and retries recheck contacts:read and each source domain: dealStage requires opportunities:read; email/link/last-contact predicates require conversations:read; booking predicates require appointments:read; form predicates require approved forms submission reads when available. Unsupported/private predicates fail closed. Requires Idempotency-Key. "
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/AudienceWriteReceipt"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or source-domain approval."},"409":{"description":"Idempotency key conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":100},"description":{"type":"string","maxLength":2000},"filterCriteria":{"$ref":"#/components/schemas/AudienceFilter"},"sortOrder":{"type":"number"},"membershipMode":{"type":"string","enum":["manual","filter","opt-in"]}},"required":["name","membershipMode"]}}}}
  /api/v1/contact-list-definitions/{id}:
    get:
      x-seedly-oauth-scope: "contact-lists:read"
      x-seedly-standard-scope: "contact-lists:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getContactListDefinitionsId"
      tags: ["Audiences"]
      summary: "GET /api/v1/contact-list-definitions/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter reads, writes, count refresh, audience pages and retries recheck contacts:read and each source domain: dealStage requires opportunities:read; email/link/last-contact predicates require conversations:read; booking predicates require appointments:read; form predicates require approved forms submission reads when available. Unsupported/private predicates fail closed. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/ContactListDefinition"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or source-domain approval."},"409":{"description":"Idempotency key conflict."},"429":{"description":"Rate limit exceeded."}}
    patch:
      x-seedly-oauth-scope: "contact-lists:write"
      x-seedly-standard-scope: "contact-lists:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "patchContactListDefinitionsId"
      tags: ["Audiences"]
      summary: "PATCH /api/v1/contact-list-definitions/{id}"
      description: "Changing filterCriteria while a scheduled, sending or paused campaign targets this list also needs campaigns:send, and is refused with a conflict when the campaigns cannot be checked. Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter reads, writes, count refresh, audience pages and retries recheck contacts:read and each source domain: dealStage requires opportunities:read; email/link/last-contact predicates require conversations:read; booking predicates require appointments:read; form predicates require approved forms submission reads when available. Unsupported/private predicates fail closed. Requires Idempotency-Key. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/AudienceWriteReceipt"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or source-domain approval."},"409":{"description":"Idempotency key conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":100},"description":{"type":"string","maxLength":2000},"filterCriteria":{"$ref":"#/components/schemas/AudienceFilter"},"sortOrder":{"type":"number"}},"required":[]}}}}
  /api/v1/contact-list-definitions/{id}/audience:
    get:
      x-seedly-oauth-scope: "contact-lists:read"
      x-seedly-standard-scope: "contact-lists:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getContactListDefinitionsIdAudience"
      tags: ["Audiences"]
      summary: "GET /api/v1/contact-list-definitions/{id}/audience"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter reads, writes, count refresh, audience pages and retries recheck contacts:read and each source domain: dealStage requires opportunities:read; email/link/last-contact predicates require conversations:read; booking predicates require appointments:read; form predicates require approved forms submission reads when available. Unsupported/private predicates fail closed. Default 25, maximum 50 records. Follow cursor even when filtered data is empty. Returns contact IDs only; membership is not send permission or deliverability. Source enrichment truncation fails closed. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":8192}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AudienceContactReference"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or source-domain approval."},"409":{"description":"Idempotency key conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/contact-list-definitions/{id}/archive:
    post:
      x-seedly-oauth-scope: "contact-lists:write"
      x-seedly-standard-scope: "contact-lists:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postContactListDefinitionsIdArchive"
      tags: ["Audiences"]
      summary: "POST /api/v1/contact-list-definitions/{id}/archive"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter reads, writes, count refresh, audience pages and retries recheck contacts:read and each source domain: dealStage requires opportunities:read; email/link/last-contact predicates require conversations:read; booking predicates require appointments:read; form predicates require approved forms submission reads when available. Unsupported/private predicates fail closed. Requires Idempotency-Key. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/AudienceWriteReceipt"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or source-domain approval."},"409":{"description":"Idempotency key conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{},"required":[]}}}}
  /api/v1/contact-list-definitions/{id}/restore:
    post:
      x-seedly-oauth-scope: "contact-lists:write"
      x-seedly-standard-scope: "contact-lists:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postContactListDefinitionsIdRestore"
      tags: ["Audiences"]
      summary: "POST /api/v1/contact-list-definitions/{id}/restore"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter reads, writes, count refresh, audience pages and retries recheck contacts:read and each source domain: dealStage requires opportunities:read; email/link/last-contact predicates require conversations:read; booking predicates require appointments:read; form predicates require approved forms submission reads when available. Unsupported/private predicates fail closed. Requires Idempotency-Key. Restoring an archived list targeted by a scheduled, sending or paused campaign also requires campaigns:send; retries recheck it."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/AudienceWriteReceipt"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or source-domain approval."},"409":{"description":"Idempotency key conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{},"required":[]}}}}
  /api/v1/contact-list-definitions/{id}/members/add:
    post:
      x-seedly-oauth-scope: "contact-lists:write"
      x-seedly-standard-scope: "contact-lists:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postContactListDefinitionsIdMembersAdd"
      tags: ["Audiences"]
      summary: "POST /api/v1/contact-list-definitions/{id}/members/add"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter reads, writes, count refresh, audience pages and retries recheck contacts:read and each source domain: dealStage requires opportunities:read; email/link/last-contact predicates require conversations:read; booking predicates require appointments:read; form predicates require approved forms submission reads when available. Unsupported/private predicates fail closed. Requires Idempotency-Key. Atomic maximum 25 unique contact IDs; never revives opt-outs. Adding also requires existing single-member add operation approval; removing requires existing single-member remove approval. Adding members to a list targeted by a scheduled, sending or paused campaign also requires campaigns:send; retries recheck it."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","processed"],"properties":{"id":{"type":"string"},"processed":{"type":"integer","minimum":1,"maximum":25}}}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or source-domain approval."},"409":{"description":"Idempotency key conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"contactIds":{"type":"array","minItems":1,"maxItems":25,"uniqueItems":true,"items":{"type":"string"}}},"required":["contactIds"]}}}}
  /api/v1/contact-list-definitions/{id}/members/remove:
    post:
      x-seedly-oauth-scope: "contact-lists:write"
      x-seedly-standard-scope: "contact-lists:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postContactListDefinitionsIdMembersRemove"
      tags: ["Audiences"]
      summary: "POST /api/v1/contact-list-definitions/{id}/members/remove"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter reads, writes, count refresh, audience pages and retries recheck contacts:read and each source domain: dealStage requires opportunities:read; email/link/last-contact predicates require conversations:read; booking predicates require appointments:read; form predicates require approved forms submission reads when available. Unsupported/private predicates fail closed. Requires Idempotency-Key. Atomic maximum 25 unique contact IDs; never revives opt-outs. Adding also requires existing single-member add operation approval; removing requires existing single-member remove approval. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","processed"],"properties":{"id":{"type":"string"},"processed":{"type":"integer","minimum":1,"maximum":25}}}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or source-domain approval."},"409":{"description":"Idempotency key conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"contactIds":{"type":"array","minItems":1,"maxItems":25,"uniqueItems":true,"items":{"type":"string"}}},"required":["contactIds"]}}}}
  /api/v1/contact-list-definitions/{id}/transactional:
    patch:
      x-seedly-oauth-scope: "contact-lists:consent"
      x-seedly-standard-scope: "contact-lists:consent"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "patchContactListDefinitionsIdTransactional"
      tags: ["Audiences"]
      summary: "PATCH /api/v1/contact-list-definitions/{id}/transactional"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter reads, writes, count refresh, audience pages and retries recheck contacts:read and each source domain: dealStage requires opportunities:read; email/link/last-contact predicates require conversations:read; booking predicates require appointments:read; form predicates require approved forms submission reads when available. Unsupported/private predicates fail closed. Requires Idempotency-Key. Specialty contact-lists:consent approval changes whether native sends bypass marketing consent rules. This does not change stored contact opt-outs. Promoting a list to transactional while a scheduled, sending or paused campaign targets it also requires campaigns:send; retries recheck it."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/AudienceWriteReceipt"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or source-domain approval."},"409":{"description":"Idempotency key conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"isTransactional":{"type":"boolean"}},"required":["isTransactional"]}}}}
  /api/v1/segments:
    get:
      x-seedly-oauth-scope: "segments:read"
      x-seedly-standard-scope: "segments:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getSegments"
      tags: ["Audiences"]
      summary: "GET /api/v1/segments"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter reads, writes, count refresh, audience pages and retries recheck contacts:read and each source domain: dealStage requires opportunities:read; email/link/last-contact predicates require conversations:read; booking predicates require appointments:read; form predicates require approved forms submission reads when available. Unsupported/private predicates fail closed. Default 25, maximum 50 records. Follow cursor even when filtered data is empty.  A row whose rule this caller may not read is kept with filterRedacted true, and with filterCriteria, contactCount and contactCountApproximate null. filterRedactedReason is hidden_pipeline for a deal stage rule when an OAuth user cannot see every pipeline, or unsupported_filter for a stored rule the API cannot validate. That record cannot be read, used or changed individually, so an unsupported rule is fixed in the app. Every other row has filterRedacted false and filterRedactedReason null. A missing scope on a rule the API can read still refuses the page."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":8192}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AudienceSegment"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or source-domain approval."},"409":{"description":"Idempotency key conflict."},"429":{"description":"Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "segments:write"
      x-seedly-standard-scope: "segments:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postSegments"
      tags: ["Audiences"]
      summary: "POST /api/v1/segments"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter reads, writes, count refresh, audience pages and retries recheck contacts:read and each source domain: dealStage requires opportunities:read; email/link/last-contact predicates require conversations:read; booking predicates require appointments:read; form predicates require approved forms submission reads when available. Unsupported/private predicates fail closed. Requires Idempotency-Key. Cached counts use native bounded scans and expose approximation on subsequent definition reads. "
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/AudienceWriteReceipt"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or source-domain approval."},"409":{"description":"Idempotency key conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","maxLength":5000},"filterCriteria":{"oneOf":[{"$ref":"#/components/schemas/AudienceFilter"},{"type":"null"}]},"folderId":{"type":["string","null"]}},"required":["name","filterCriteria"]}}}}
  /api/v1/segments/{id}:
    get:
      x-seedly-oauth-scope: "segments:read"
      x-seedly-standard-scope: "segments:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getSegmentsId"
      tags: ["Audiences"]
      summary: "GET /api/v1/segments/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter reads, writes, count refresh, audience pages and retries recheck contacts:read and each source domain: dealStage requires opportunities:read; email/link/last-contact predicates require conversations:read; booking predicates require appointments:read; form predicates require approved forms submission reads when available. Unsupported/private predicates fail closed. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/AudienceSegment"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or source-domain approval."},"409":{"description":"Idempotency key conflict."},"429":{"description":"Rate limit exceeded."}}
    patch:
      x-seedly-oauth-scope: "segments:write"
      x-seedly-standard-scope: "segments:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "patchSegmentsId"
      tags: ["Audiences"]
      summary: "PATCH /api/v1/segments/{id}"
      description: "Changing filterCriteria while an active workflow is triggered by this segment also needs workflows:publish, and is refused with a conflict when the workflows cannot be checked. Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter reads, writes, count refresh, audience pages and retries recheck contacts:read and each source domain: dealStage requires opportunities:read; email/link/last-contact predicates require conversations:read; booking predicates require appointments:read; form predicates require approved forms submission reads when available. Unsupported/private predicates fail closed. Requires Idempotency-Key. Cached counts use native bounded scans and expose approximation on subsequent definition reads. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/AudienceWriteReceipt"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or source-domain approval."},"409":{"description":"Idempotency key conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","maxLength":5000},"filterCriteria":{"oneOf":[{"$ref":"#/components/schemas/AudienceFilter"},{"type":"null"}]},"folderId":{"type":["string","null"]}},"required":[]}}}}
    delete:
      x-seedly-oauth-scope: "segments:delete"
      x-seedly-standard-scope: "segments:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "deleteSegmentsId"
      tags: ["Audiences"]
      summary: "DELETE /api/v1/segments/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter reads, writes, count refresh, audience pages and retries recheck contacts:read and each source domain: dealStage requires opportunities:read; email/link/last-contact predicates require conversations:read; booking predicates require appointments:read; form predicates require approved forms submission reads when available. Unsupported/private predicates fail closed. Requires Idempotency-Key. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/AudienceWriteReceipt"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or source-domain approval."},"409":{"description":"Idempotency key conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/segments/{id}/audience:
    get:
      x-seedly-oauth-scope: "segments:read"
      x-seedly-standard-scope: "segments:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getSegmentsIdAudience"
      tags: ["Audiences"]
      summary: "GET /api/v1/segments/{id}/audience"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter reads, writes, count refresh, audience pages and retries recheck contacts:read and each source domain: dealStage requires opportunities:read; email/link/last-contact predicates require conversations:read; booking predicates require appointments:read; form predicates require approved forms submission reads when available. Unsupported/private predicates fail closed. Default 25, maximum 50 records. Follow cursor even when filtered data is empty. Returns contact IDs only; membership is not send permission or deliverability. Source enrichment truncation fails closed. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":8192}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AudienceContactReference"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or source-domain approval."},"409":{"description":"Idempotency key conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/segment-folders:
    get:
      x-seedly-oauth-scope: "segments:read"
      x-seedly-standard-scope: "segments:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getSegmentFolders"
      tags: ["Audiences"]
      summary: "GET /api/v1/segment-folders"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter reads, writes, count refresh, audience pages and retries recheck contacts:read and each source domain: dealStage requires opportunities:read; email/link/last-contact predicates require conversations:read; booking predicates require appointments:read; form predicates require approved forms submission reads when available. Unsupported/private predicates fail closed. Default 25, maximum 50 records. Follow cursor even when filtered data is empty. "
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":8192}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AudienceSegmentFolder"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or source-domain approval."},"409":{"description":"Idempotency key conflict."},"429":{"description":"Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "segments:write"
      x-seedly-standard-scope: "segments:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postSegmentFolders"
      tags: ["Audiences"]
      summary: "POST /api/v1/segment-folders"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter reads, writes, count refresh, audience pages and retries recheck contacts:read and each source domain: dealStage requires opportunities:read; email/link/last-contact predicates require conversations:read; booking predicates require appointments:read; form predicates require approved forms submission reads when available. Unsupported/private predicates fail closed. Requires Idempotency-Key. "
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/AudienceWriteReceipt"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or source-domain approval."},"409":{"description":"Idempotency key conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":255},"parentId":{"type":"string"}},"required":["name"]}}}}
  /api/v1/segments/{id}/refresh-count:
    post:
      x-seedly-oauth-scope: "segments:write"
      x-seedly-standard-scope: "segments:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postSegmentsIdRefreshCount"
      tags: ["Audiences"]
      summary: "POST /api/v1/segments/{id}/refresh-count"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter reads, writes, count refresh, audience pages and retries recheck contacts:read and each source domain: dealStage requires opportunities:read; email/link/last-contact predicates require conversations:read; booking predicates require appointments:read; form predicates require approved forms submission reads when available. Unsupported/private predicates fail closed. Requires Idempotency-Key. Cached counts use native bounded scans and expose approximation on subsequent definition reads. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/AudienceWriteReceipt"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or source-domain approval."},"409":{"description":"Idempotency key conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{},"required":[]}}}}
  /api/v1/segment-folders/{id}:
    patch:
      x-seedly-oauth-scope: "segments:write"
      x-seedly-standard-scope: "segments:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "patchSegmentFoldersId"
      tags: ["Audiences"]
      summary: "PATCH /api/v1/segment-folders/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter reads, writes, count refresh, audience pages and retries recheck contacts:read and each source domain: dealStage requires opportunities:read; email/link/last-contact predicates require conversations:read; booking predicates require appointments:read; form predicates require approved forms submission reads when available. Unsupported/private predicates fail closed. Requires Idempotency-Key. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/AudienceWriteReceipt"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or source-domain approval."},"409":{"description":"Idempotency key conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":255}},"required":[]}}}}
    delete:
      x-seedly-oauth-scope: "segments:delete"
      x-seedly-standard-scope: "segments:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "deleteSegmentFoldersId"
      tags: ["Audiences"]
      summary: "DELETE /api/v1/segment-folders/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter reads, writes, count refresh, audience pages and retries recheck contacts:read and each source domain: dealStage requires opportunities:read; email/link/last-contact predicates require conversations:read; booking predicates require appointments:read; form predicates require approved forms submission reads when available. Unsupported/private predicates fail closed. Requires Idempotency-Key. Moves at most 100 contained segments and child folders to root atomically. Larger folders are rejected here; use POST /api/v1/segment-folders/{id}/deletion-jobs. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/AudienceWriteReceipt"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or source-domain approval."},"409":{"description":"Idempotency key conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/segments/preview:
    post:
      x-seedly-oauth-scope: "segments:read"
      x-seedly-standard-scope: "segments:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postSegmentsPreview"
      tags: ["Audiences"]
      summary: "POST /api/v1/segments/preview"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter sources are rechecked: contacts:read always, plus each source domain, and customFields.<name> predicates require an active scalar contact field definition and approved contact field-value reads. Evaluates an unsaved filter without storing it. Scans at most 3000 contacts; isApproximate means more contacts exist and approximate means an enrichment read stopped early. Returns a count and up to 25 contact IDs, never contact fields or suppression figures."
      parameters: []
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["filterCriteria"],"properties":{"filterCriteria":{},"limit":{"type":"integer","minimum":0,"maximum":25}}}}}}
  /api/v1/segment-resolution-jobs/{id}/members:
    get:
      x-seedly-oauth-scope: "segments:read"
      x-seedly-standard-scope: "segments:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getSegmentResolutionJobsIdMembers"
      tags: ["Audiences"]
      summary: "GET /api/v1/segment-resolution-jobs/{id}/members"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Pages contact IDs from a complete resolution job. Available for seven days to the starting credential. Point-in-time result; contacts since deleted are omitted, so a page can be empty while hasMore is true."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/segment-resolution-jobs/{id}:
    get:
      x-seedly-oauth-scope: "segments:read"
      x-seedly-standard-scope: "segments:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getSegmentResolutionJobsId"
      tags: ["Audiences"]
      summary: "GET /api/v1/segment-resolution-jobs/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Reads durable job progress. Job status is visible only to the starting credential. Each batch rechecks authority and relationships; revocation or changed state pauses work. Completed batches stay in place when a job pauses, fails or is cancelled. Resume adopts the current verified credential."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/contact-list-definitions/preview:
    post:
      x-seedly-oauth-scope: "contact-lists:read"
      x-seedly-standard-scope: "contact-lists:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postContactListDefinitionsPreview"
      tags: ["Audiences"]
      summary: "POST /api/v1/contact-list-definitions/preview"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter sources are rechecked: contacts:read always, plus each source domain, and customFields.<name> predicates require an active scalar contact field definition and approved contact field-value reads. Evaluates unsaved list criteria with the native list resolver without storing them. Scans at most 3000 contacts. Returns a count and up to 25 contact IDs."
      parameters: []
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["filterCriteria"],"properties":{"filterCriteria":{},"limit":{"type":"integer","minimum":0,"maximum":25}}}}}}
  /api/v1/contact-list-member-jobs/{id}:
    get:
      x-seedly-oauth-scope: "contact-lists:read"
      x-seedly-standard-scope: "contact-lists:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getContactListMemberJobsId"
      tags: ["Audiences"]
      summary: "GET /api/v1/contact-list-member-jobs/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Reads durable job progress. Job status is visible only to the starting credential. Each batch rechecks authority and relationships; revocation or changed state pauses work. Completed batches stay in place when a job pauses, fails or is cancelled. Resume adopts the current verified credential."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/contact-list-resolution-jobs/{id}/members:
    get:
      x-seedly-oauth-scope: "contact-lists:read"
      x-seedly-standard-scope: "contact-lists:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getContactListResolutionJobsIdMembers"
      tags: ["Audiences"]
      summary: "GET /api/v1/contact-list-resolution-jobs/{id}/members"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Pages contact IDs from a complete list resolution job. Available for seven days to the starting credential. Point-in-time result; contacts since deleted are omitted."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/contact-list-resolution-jobs/{id}:
    get:
      x-seedly-oauth-scope: "contact-lists:read"
      x-seedly-standard-scope: "contact-lists:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getContactListResolutionJobsId"
      tags: ["Audiences"]
      summary: "GET /api/v1/contact-list-resolution-jobs/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Reads durable job progress. Job status is visible only to the starting credential. Each batch rechecks authority and relationships; revocation or changed state pauses work. Completed batches stay in place when a job pauses, fails or is cancelled. Resume adopts the current verified credential."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/contact-list-definitions/{id}/member-jobs:
    post:
      x-seedly-oauth-scope: "contact-lists:write"
      x-seedly-standard-scope: "contact-lists:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postContactListDefinitionsIdMemberJobs"
      tags: ["Audiences"]
      summary: "POST /api/v1/contact-list-definitions/{id}/member-jobs"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Requires contacts:read and Idempotency-Key. Starts a durable manual list membership job for 1 to 2000 unique contact IDs, processed 25 at a time through the same consent checks as single membership changes. Contacts that are unavailable or refused by consent or suppression are counted and skipped. Job status is visible only to the starting credential. Each batch rechecks authority and relationships; revocation or changed state pauses work. Completed batches stay in place when a job pauses, fails or is cancelled. Resume adopts the current verified credential.Add jobs targeting a scheduled, sending or paused campaign also require campaigns:send at start and on every batch; remove jobs keep their existing permission."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["operation","contactIds"],"properties":{"operation":{"type":"string","enum":["add","remove"]},"contactIds":{"type":"array","minItems":1,"maxItems":2000,"uniqueItems":true,"items":{"type":"string"}}}}}}}
  /api/v1/contact-list-member-jobs/{id}/resume:
    post:
      x-seedly-oauth-scope: "contact-lists:write"
      x-seedly-standard-scope: "contact-lists:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postContactListMemberJobsIdResume"
      tags: ["Audiences"]
      summary: "POST /api/v1/contact-list-member-jobs/{id}/resume"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Requires Idempotency-Key. Resumes paused or stalled work. Job status is visible only to the starting credential. Each batch rechecks authority and relationships; revocation or changed state pauses work. Completed batches stay in place when a job pauses, fails or is cancelled. Resume adopts the current verified credential.Add jobs targeting a scheduled, sending or paused campaign also require campaigns:send to resume; each batch rechecks it."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/contact-list-member-jobs/{id}/cancel:
    post:
      x-seedly-oauth-scope: "contact-lists:write"
      x-seedly-standard-scope: "contact-lists:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postContactListMemberJobsIdCancel"
      tags: ["Audiences"]
      summary: "POST /api/v1/contact-list-member-jobs/{id}/cancel"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Requires Idempotency-Key. Stops remaining work. Job status is visible only to the starting credential. Each batch rechecks authority and relationships; revocation or changed state pauses work. Completed batches stay in place when a job pauses, fails or is cancelled. Resume adopts the current verified credential."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/contact-list-definitions/{id}/resolution-jobs:
    post:
      x-seedly-oauth-scope: "contact-lists:write"
      x-seedly-standard-scope: "contact-lists:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postContactListDefinitionsIdResolutionJobs"
      tags: ["Audiences"]
      summary: "POST /api/v1/contact-list-definitions/{id}/resolution-jobs"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter sources are rechecked: contacts:read always, plus each source domain, and customFields.<name> predicates require an active scalar contact field definition and approved contact field-value reads. Requires Idempotency-Key. Resolves a saved filter list over every contact, excluding per-list opt-outs, with the same exact-or-indeterminate rule as segments. A changed filter pauses the job. Results are retained for seven days. Job status is visible only to the starting credential. Each batch rechecks authority and relationships; revocation or changed state pauses work. Completed batches stay in place when a job pauses, fails or is cancelled. Resume adopts the current verified credential."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/contact-list-resolution-jobs/{id}/resume:
    post:
      x-seedly-oauth-scope: "contact-lists:write"
      x-seedly-standard-scope: "contact-lists:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postContactListResolutionJobsIdResume"
      tags: ["Audiences"]
      summary: "POST /api/v1/contact-list-resolution-jobs/{id}/resume"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Requires Idempotency-Key. Resumes paused or stalled work. Job status is visible only to the starting credential. Each batch rechecks authority and relationships; revocation or changed state pauses work. Completed batches stay in place when a job pauses, fails or is cancelled. Resume adopts the current verified credential."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/contact-list-resolution-jobs/{id}/cancel:
    post:
      x-seedly-oauth-scope: "contact-lists:write"
      x-seedly-standard-scope: "contact-lists:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postContactListResolutionJobsIdCancel"
      tags: ["Audiences"]
      summary: "POST /api/v1/contact-list-resolution-jobs/{id}/cancel"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Requires Idempotency-Key. Stops remaining work. Job status is visible only to the starting credential. Each batch rechecks authority and relationships; revocation or changed state pauses work. Completed batches stay in place when a job pauses, fails or is cancelled. Resume adopts the current verified credential."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/segment-folders/{id}/deletion-jobs:
    post:
      x-seedly-oauth-scope: "segments:delete"
      x-seedly-standard-scope: "segments:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postSegmentFoldersIdDeletionJobs"
      tags: ["Audiences"]
      summary: "POST /api/v1/segment-folders/{id}/deletion-jobs"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Requires Idempotency-Key. Moves any number of contained segments and child folders to root in batches of 25, then removes the folder only after both are empty. Descendants are retained. Job status is visible only to the starting credential. Each batch rechecks authority and relationships; revocation or changed state pauses work. Completed batches stay in place when a job pauses, fails or is cancelled. Resume adopts the current verified credential."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/segment-folder-deletions/{id}:
    get:
      x-seedly-oauth-scope: "segments:delete"
      x-seedly-standard-scope: "segments:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getSegmentFolderDeletionsId"
      tags: ["Audiences"]
      summary: "GET /api/v1/segment-folder-deletions/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Reads durable job progress. Job status is visible only to the starting credential. Each batch rechecks authority and relationships; revocation or changed state pauses work. Completed batches stay in place when a job pauses, fails or is cancelled. Resume adopts the current verified credential."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/segment-folder-deletions/{id}/resume:
    post:
      x-seedly-oauth-scope: "segments:delete"
      x-seedly-standard-scope: "segments:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postSegmentFolderDeletionsIdResume"
      tags: ["Audiences"]
      summary: "POST /api/v1/segment-folder-deletions/{id}/resume"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Requires Idempotency-Key. Resumes paused or stalled work. Job status is visible only to the starting credential. Each batch rechecks authority and relationships; revocation or changed state pauses work. Completed batches stay in place when a job pauses, fails or is cancelled. Resume adopts the current verified credential."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/segment-folder-deletions/{id}/cancel:
    post:
      x-seedly-oauth-scope: "segments:delete"
      x-seedly-standard-scope: "segments:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postSegmentFolderDeletionsIdCancel"
      tags: ["Audiences"]
      summary: "POST /api/v1/segment-folder-deletions/{id}/cancel"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Requires Idempotency-Key. Stops remaining work. Job status is visible only to the starting credential. Each batch rechecks authority and relationships; revocation or changed state pauses work. Completed batches stay in place when a job pauses, fails or is cancelled. Resume adopts the current verified credential."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/segments/{id}/resolution-jobs:
    post:
      x-seedly-oauth-scope: "segments:write"
      x-seedly-standard-scope: "segments:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postSegmentsIdResolutionJobs"
      tags: ["Audiences"]
      summary: "POST /api/v1/segments/{id}/resolution-jobs"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Filter sources are rechecked: contacts:read always, plus each source domain, and customFields.<name> predicates require an active scalar contact field definition and approved contact field-value reads. Requires Idempotency-Key. Resolves the saved filter over every contact using per-contact history far beyond the interactive limits. A contact whose history still cannot be read completely counts as indeterminate and is never guessed. On completion the cached segment count is updated. A changed filter pauses the job. Results are retained for seven days. Job status is visible only to the starting credential. Each batch rechecks authority and relationships; revocation or changed state pauses work. Completed batches stay in place when a job pauses, fails or is cancelled. Resume adopts the current verified credential."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/segment-resolution-jobs/{id}/resume:
    post:
      x-seedly-oauth-scope: "segments:write"
      x-seedly-standard-scope: "segments:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postSegmentResolutionJobsIdResume"
      tags: ["Audiences"]
      summary: "POST /api/v1/segment-resolution-jobs/{id}/resume"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Requires Idempotency-Key. Resumes paused or stalled work. Job status is visible only to the starting credential. Each batch rechecks authority and relationships; revocation or changed state pauses work. Completed batches stay in place when a job pauses, fails or is cancelled. Resume adopts the current verified credential."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/segment-resolution-jobs/{id}/cancel:
    post:
      x-seedly-oauth-scope: "segments:write"
      x-seedly-standard-scope: "segments:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postSegmentResolutionJobsIdCancel"
      tags: ["Audiences"]
      summary: "POST /api/v1/segment-resolution-jobs/{id}/cancel"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Requires Idempotency-Key. Stops remaining work. Job status is visible only to the starting credential. Each batch rechecks authority and relationships; revocation or changed state pauses work. Completed batches stay in place when a job pauses, fails or is cancelled. Resume adopts the current verified credential."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/email-template-library:
    get:
      x-seedly-oauth-scope: "templates:read"
      x-seedly-standard-scope: "templates:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getEmailTemplateLibrary"
      tags: ["Templates"]
      summary: "GET /api/v1/email-template-library"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Lists location-owned shared single and sequence email templates as metadata. Layouts stay on /api/v1/email-templates. Agency, private and prebuilt rows are not listed here. Pages scan at most 50 rows, so a page can be empty while hasMore is true."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"templateType","in":"query","schema":{"type":"string"}},{"name":"folderId","in":"query","schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "templates:write"
      x-seedly-standard-scope: "templates:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postEmailTemplateLibrary"
      tags: ["Templates"]
      summary: "POST /api/v1/email-template-library"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Returns a durable minimal receipt. Creates a single or sequence template. Authored HTML is sanitized with the email profile and stored as one native HTML block, so the native canvas opens the same content. listId also requires contact-lists:read. Sending is separate authority."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"},"templateType":{"type":"string","enum":["single","sequence"]},"subject":{"type":"string"},"preheader":{"type":"string"},"bodyHtml":{"type":"string"},"steps":{"type":"array","maxItems":20,"items":{"type":"object","additionalProperties":false,"required":["subject","bodyHtml","delayMinutes"],"properties":{"subject":{"type":"string"},"preheader":{"type":"string","maxLength":200},"bodyHtml":{"type":"string"},"delayMinutes":{"type":"integer","minimum":0,"maximum":525600}}}},"category":{"type":"string"},"listId":{"type":"string"},"folderId":{"type":"string"}}}}}}
  /api/v1/email-template-library/{id}:
    get:
      x-seedly-oauth-scope: "templates:read"
      x-seedly-standard-scope: "templates:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getEmailTemplateLibraryId"
      tags: ["Templates"]
      summary: "GET /api/v1/email-template-library/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Returns template content, including native canvas blocks and sequence steps. An image published from a tenant file appears as its fileId, and as file:<id> in bodyHtml, never as a storage URL."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
    patch:
      x-seedly-oauth-scope: "templates:write"
      x-seedly-standard-scope: "templates:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "patchEmailTemplateLibraryId"
      tags: ["Templates"]
      summary: "PATCH /api/v1/email-template-library/{id}"
      description: "A template bound as a send default also needs the matching send scope, and one that cannot be proved unbound is refused with a conflict. Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Returns a durable minimal receipt. Edits template fields. Replacing the body of a template built with other native canvas blocks requires replaceCanvas true, because those blocks are replaced by one HTML block. HTML-mode templates are edited natively."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string"},"subject":{"type":"string"},"preheader":{"type":"string"},"bodyHtml":{"type":"string"},"steps":{"type":"array","maxItems":20,"items":{"type":"object","additionalProperties":false,"required":["subject","bodyHtml","delayMinutes"],"properties":{"subject":{"type":"string"},"preheader":{"type":"string","maxLength":200},"bodyHtml":{"type":"string"},"delayMinutes":{"type":"integer","minimum":0,"maximum":525600}}}},"category":{"type":"string"},"listId":{"type":["string","null"]},"replaceCanvas":{"type":"boolean","enum":[true]}}}}}}
    delete:
      x-seedly-oauth-scope: "templates:delete"
      x-seedly-standard-scope: "templates:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "deleteEmailTemplateLibraryId"
      tags: ["Templates"]
      summary: "DELETE /api/v1/email-template-library/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Returns a durable minimal receipt. Deletes a location-owned sendable template using native semantics: references elsewhere are not cascaded."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/email-template-library/canvas:
    post:
      x-seedly-oauth-scope: "templates:write"
      x-seedly-standard-scope: "templates:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "createEmailTemplateCanvas"
      tags: ["Templates"]
      summary: "POST /api/v1/email-template-library/canvas"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Creates a single or sequence template from structured blocks. Text blocks accept p, h1 to h3, lists, blockquote, br, strong, em, s, u and links, and anything else is refused. Custom HTML and footer blocks are native-only; authored HTML stays on the bodyHtml routes. The server renders the stored body with the native email serializer. fileId references need files:read and an unlinked PNG, JPEG, GIF or WebP file of this location, at most 5 MiB, proved on every attempt including replays. A published file can no longer be deleted. listId also requires contact-lists:read and brandStyleId also requires brand-styles:read. Sending is separate authority."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"},"templateType":{"type":"string","enum":["single","sequence"]},"subject":{"type":"string"},"preheader":{"type":"string","maxLength":200},"blocks":{"type":"array","maxItems":100,"items":{"type":"object","additionalProperties":false,"required":["id","type","data"],"properties":{"id":{"type":"string","maxLength":100},"type":{"type":"string","enum":["heading","text","image","button","divider","spacer","columns","video","social","logo","countdown","review_link"]},"data":{"type":"object","description":"Fields for the block type. Unknown fields are refused. A new image, logo or video thumbnail uses fileId or thumbnailFileId. A public HTTPS url is accepted only where the canvas already holds it."}}}},"globalStyles":{"type":"object","additionalProperties":false,"properties":{"bgColor":{"type":"string"},"bodyColor":{"type":"string"},"fontFamily":{"type":"string"},"linkColor":{"type":"string"},"buttonColor":{"type":"string"},"contentWidth":{"type":"number","minimum":320,"maximum":1200},"headingDefaults":{"type":"object"},"textDefaults":{"type":"object"},"buttonDefaults":{"type":"object"},"imageDefaults":{"type":"object"},"dividerDefaults":{"type":"object"},"spacerDefaults":{"type":"object"}}},"steps":{"type":"array","minItems":1,"maxItems":20,"items":{"type":"object","additionalProperties":false,"required":["subject","blocks","delayMinutes"],"properties":{"subject":{"type":"string"},"preheader":{"type":"string","maxLength":200},"blocks":{"type":"array","maxItems":100,"items":{"type":"object","additionalProperties":false,"required":["id","type","data"],"properties":{"id":{"type":"string","maxLength":100},"type":{"type":"string","enum":["heading","text","image","button","divider","spacer","columns","video","social","logo","countdown","review_link"]},"data":{"type":"object","description":"Fields for the block type. Unknown fields are refused. A new image, logo or video thumbnail uses fileId or thumbnailFileId. A public HTTPS url is accepted only where the canvas already holds it."}}}},"globalStyles":{"type":"object","additionalProperties":false,"properties":{"bgColor":{"type":"string"},"bodyColor":{"type":"string"},"fontFamily":{"type":"string"},"linkColor":{"type":"string"},"buttonColor":{"type":"string"},"contentWidth":{"type":"number","minimum":320,"maximum":1200},"headingDefaults":{"type":"object"},"textDefaults":{"type":"object"},"buttonDefaults":{"type":"object"},"imageDefaults":{"type":"object"},"dividerDefaults":{"type":"object"},"spacerDefaults":{"type":"object"}}},"delayMinutes":{"type":"integer","minimum":0,"maximum":525600}}}},"category":{"type":"string"},"listId":{"type":"string"},"folderId":{"type":"string"},"brandStyleId":{"type":"string"}}}}}}
  /api/v1/email-template-library/{id}/canvas:
    get:
      x-seedly-oauth-scope: "templates:read"
      x-seedly-standard-scope: "templates:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getEmailTemplateCanvas"
      tags: ["Templates"]
      summary: "GET /api/v1/email-template-library/{id}/canvas"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Returns the structured canvas: writable design tokens and blocks, with file IDs rather than storage URLs. A stored block this API cannot represent is returned as id, type and unsupported true. writable is false when a replace needs replaceCanvas."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
    put:
      x-seedly-oauth-scope: "templates:write"
      x-seedly-standard-scope: "templates:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "replaceEmailTemplateCanvas"
      tags: ["Templates"]
      summary: "PUT /api/v1/email-template-library/{id}/canvas"
      description: "A template bound as a send default also needs the matching send scope, and one that cannot be proved unbound is refused with a conflict. Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Replaces the canvas and renders the body the next send uses. Subject, preheader, list and folder are unchanged. Overwriting content this API cannot represent requires replaceCanvas true. Sequence templates send steps. HTML-mode templates are edited natively. Text blocks accept p, h1 to h3, lists, blockquote, br, strong, em, s, u and links, and anything else is refused. Custom HTML and footer blocks are native-only; authored HTML stays on the bodyHtml routes. The server renders the stored body with the native email serializer. fileId references need files:read and an unlinked PNG, JPEG, GIF or WebP file of this location, at most 5 MiB, proved on every attempt including replays. A published file can no longer be deleted."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"blocks":{"type":"array","maxItems":100,"items":{"type":"object","additionalProperties":false,"required":["id","type","data"],"properties":{"id":{"type":"string","maxLength":100},"type":{"type":"string","enum":["heading","text","image","button","divider","spacer","columns","video","social","logo","countdown","review_link"]},"data":{"type":"object","description":"Fields for the block type. Unknown fields are refused. A new image, logo or video thumbnail uses fileId or thumbnailFileId. A public HTTPS url is accepted only where the canvas already holds it."}}}},"globalStyles":{"type":"object","additionalProperties":false,"properties":{"bgColor":{"type":"string"},"bodyColor":{"type":"string"},"fontFamily":{"type":"string"},"linkColor":{"type":"string"},"buttonColor":{"type":"string"},"contentWidth":{"type":"number","minimum":320,"maximum":1200},"headingDefaults":{"type":"object"},"textDefaults":{"type":"object"},"buttonDefaults":{"type":"object"},"imageDefaults":{"type":"object"},"dividerDefaults":{"type":"object"},"spacerDefaults":{"type":"object"}}},"steps":{"type":"array","minItems":1,"maxItems":20,"items":{"type":"object","additionalProperties":false,"required":["subject","blocks","delayMinutes"],"properties":{"subject":{"type":"string"},"preheader":{"type":"string","maxLength":200},"blocks":{"type":"array","maxItems":100,"items":{"type":"object","additionalProperties":false,"required":["id","type","data"],"properties":{"id":{"type":"string","maxLength":100},"type":{"type":"string","enum":["heading","text","image","button","divider","spacer","columns","video","social","logo","countdown","review_link"]},"data":{"type":"object","description":"Fields for the block type. Unknown fields are refused. A new image, logo or video thumbnail uses fileId or thumbnailFileId. A public HTTPS url is accepted only where the canvas already holds it."}}}},"globalStyles":{"type":"object","additionalProperties":false,"properties":{"bgColor":{"type":"string"},"bodyColor":{"type":"string"},"fontFamily":{"type":"string"},"linkColor":{"type":"string"},"buttonColor":{"type":"string"},"contentWidth":{"type":"number","minimum":320,"maximum":1200},"headingDefaults":{"type":"object"},"textDefaults":{"type":"object"},"buttonDefaults":{"type":"object"},"imageDefaults":{"type":"object"},"dividerDefaults":{"type":"object"},"spacerDefaults":{"type":"object"}}},"delayMinutes":{"type":"integer","minimum":0,"maximum":525600}}}},"replaceCanvas":{"type":"boolean","enum":[true]}}}}}}
  /api/v1/email-template-folders:
    get:
      x-seedly-oauth-scope: "templates:read"
      x-seedly-standard-scope: "templates:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getEmailTemplateFolders"
      tags: ["Templates"]
      summary: "GET /api/v1/email-template-folders"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Lists template folders."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "templates:write"
      x-seedly-standard-scope: "templates:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postEmailTemplateFolders"
      tags: ["Templates"]
      summary: "POST /api/v1/email-template-folders"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Returns a durable minimal receipt. Creates a folder."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string","maxLength":100},"parentId":{"type":"string"}}}}}}
  /api/v1/email-template-starters:
    get:
      x-seedly-oauth-scope: "templates:read"
      x-seedly-standard-scope: "templates:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getEmailTemplateStarters"
      tags: ["Templates"]
      summary: "GET /api/v1/email-template-starters"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Lists read-only agency starters: source is prebuilt (default) or agency."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"source","in":"query","schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/email-template-starters/{id}:
    get:
      x-seedly-oauth-scope: "templates:read"
      x-seedly-standard-scope: "templates:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getEmailTemplateStartersId"
      tags: ["Templates"]
      summary: "GET /api/v1/email-template-starters/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Returns one read-only agency starter."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/email-template-library/{id}/duplicate:
    post:
      x-seedly-oauth-scope: "templates:write"
      x-seedly-standard-scope: "templates:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postEmailTemplateLibraryIdDuplicate"
      tags: ["Templates"]
      summary: "POST /api/v1/email-template-library/{id}/duplicate"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Returns a durable minimal receipt. Also requires templates:read. Copies the template and its authoring mode."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/email-template-library/{id}/brand-style:
    post:
      x-seedly-oauth-scope: "templates:write"
      x-seedly-standard-scope: "templates:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postEmailTemplateLibraryIdBrandStyle"
      tags: ["Templates"]
      summary: "POST /api/v1/email-template-library/{id}/brand-style"
      description: "A template bound as a send default also needs the matching send scope, and one that cannot be proved unbound is refused with a conflict. Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Returns a durable minimal receipt. Applies a same-location brand style to the template global styles."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["brandStyleId"],"properties":{"brandStyleId":{"type":"string"}}}}}}
  /api/v1/email-template-library/{id}/folder:
    patch:
      x-seedly-oauth-scope: "templates:write"
      x-seedly-standard-scope: "templates:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "patchEmailTemplateLibraryIdFolder"
      tags: ["Templates"]
      summary: "PATCH /api/v1/email-template-library/{id}/folder"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Returns a durable minimal receipt. Moves a template. Null moves it to root."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["folderId"],"properties":{"folderId":{"type":["string","null"]}}}}}}
  /api/v1/email-template-folders/{id}:
    patch:
      x-seedly-oauth-scope: "templates:write"
      x-seedly-standard-scope: "templates:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "patchEmailTemplateFoldersId"
      tags: ["Templates"]
      summary: "PATCH /api/v1/email-template-folders/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Returns a durable minimal receipt. Renames a folder."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string","maxLength":100}}}}}}
    delete:
      x-seedly-oauth-scope: "templates:delete"
      x-seedly-standard-scope: "templates:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "deleteEmailTemplateFoldersId"
      tags: ["Templates"]
      summary: "DELETE /api/v1/email-template-folders/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Returns a durable minimal receipt. Moves at most 100 contained templates and child folders to root atomically, then removes the folder. Larger folders are refused."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/email-template-starters/{id}/clone:
    post:
      x-seedly-oauth-scope: "templates:write"
      x-seedly-standard-scope: "templates:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postEmailTemplateStartersIdClone"
      tags: ["Templates"]
      summary: "POST /api/v1/email-template-starters/{id}/clone"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Returns a durable minimal receipt. Also requires templates:read. Copies an agency starter into this location as an ordinary template."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/brand-styles:
    get:
      x-seedly-oauth-scope: "brand-styles:read"
      x-seedly-standard-scope: "brand-styles:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getBrandStyles"
      tags: ["Templates"]
      summary: "GET /api/v1/brand-styles"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Lists presentation tokens. Logo storage is reported only as logoConfigured."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "brand-styles:write"
      x-seedly-standard-scope: "brand-styles:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postBrandStyles"
      tags: ["Templates"]
      summary: "POST /api/v1/brand-styles"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Creates a style through native validation. Logos are set in the app."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"properties":{"name":{"type":"string"},"isDefault":{"type":"boolean"},"primaryColor":{"type":"string"},"backgroundColor":{"type":"string"},"fontFamily":{"type":"string"}}}}}}
  /api/v1/brand-styles/{id}:
    get:
      x-seedly-oauth-scope: "brand-styles:read"
      x-seedly-standard-scope: "brand-styles:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getBrandStylesId"
      tags: ["Templates"]
      summary: "GET /api/v1/brand-styles/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Returns presentation tokens for one style."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
    patch:
      x-seedly-oauth-scope: "brand-styles:write"
      x-seedly-standard-scope: "brand-styles:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "patchBrandStylesId"
      tags: ["Templates"]
      summary: "PATCH /api/v1/brand-styles/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Edits a style through native validation. Logos are set in the app."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"properties":{"name":{"type":"string"},"isDefault":{"type":"boolean"},"primaryColor":{"type":"string"},"backgroundColor":{"type":"string"},"fontFamily":{"type":"string"}}}}}}
    delete:
      x-seedly-oauth-scope: "brand-styles:delete"
      x-seedly-standard-scope: "brand-styles:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "deleteBrandStylesId"
      tags: ["Templates"]
      summary: "DELETE /api/v1/brand-styles/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Deletes a style. Calendars using it are cleared and the next style becomes default, as in the app."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/brand-styles/{id}/duplicate:
    post:
      x-seedly-oauth-scope: "brand-styles:write"
      x-seedly-standard-scope: "brand-styles:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "duplicateBrandStyle"
      tags: ["Templates"]
      summary: "POST /api/v1/brand-styles/{id}/duplicate"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Copies every token under the name with (Copy) added. The copy is never the default and has no logo. A style above 64 KiB, or one holding a value native validation refuses, returns 409."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}
  /api/v1/brand-styles/{id}/logo:
    put:
      x-seedly-oauth-scope: "brand-styles:write"
      x-seedly-standard-scope: "brand-styles:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "setBrandStyleLogo"
      tags: ["Templates"]
      summary: "PUT /api/v1/brand-styles/{id}/logo"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Also requires files:read. Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Sets the logo from an unlinked PNG, JPEG, GIF or WebP file of this location, at most 5 MiB, proved on every attempt including replays. A published file can no longer be deleted. An existing public HTTPS logo stays in place until this replaces it."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["fileId"],"properties":{"fileId":{"type":"string"}}}}}}
    delete:
      x-seedly-oauth-scope: "brand-styles:write"
      x-seedly-standard-scope: "brand-styles:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "clearBrandStyleLogo"
      tags: ["Templates"]
      summary: "DELETE /api/v1/brand-styles/{id}/logo"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Removes the logo from this style. A file record stays in the file library."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/forms/{id}/quarantined-submissions:
    get:
      x-seedly-oauth-scope: "forms:read"
      x-seedly-standard-scope: "forms:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getFormsIdQuarantinedSubmissions"
      tags: ["Forms"]
      summary: "GET /api/v1/forms/{id}/quarantined-submissions"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Also requires contacts:read. Lists submissions held by spam detection, with safe answers and reasons. Pages scan at most 50 rows, so a page can be empty while hasMore is true."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/forms/{id}/submission-exports:
    post:
      x-seedly-oauth-scope: "forms:read"
      x-seedly-standard-scope: "forms:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postFormsIdSubmissionExports"
      tags: ["Forms"]
      summary: "POST /api/v1/forms/{id}/submission-exports"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Also requires contacts:read. Starts a durable export of safe answers, without visitor links, tokens, IP addresses or storage references. Attachments stay behind the authenticated attachment route. Results are retained for seven days. Status is visible only to the starting credential. Each batch rechecks authority; revocation pauses work and completed batches stay in place. Resume adopts the current verified credential."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/form-submission-exports/{id}:
    get:
      x-seedly-oauth-scope: "forms:read"
      x-seedly-standard-scope: "forms:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getFormSubmissionExportsId"
      tags: ["Forms"]
      summary: "GET /api/v1/form-submission-exports/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Reads export progress. Status is visible only to the starting credential. An export closed by expiry, cancellation or contact erasure reports purged: true and its parts are gone; a running or paused export voided by erasure ends cancelled with failureCode contact_erased. Each batch rechecks authority; revocation pauses work and completed batches stay in place. Resume adopts the current verified credential."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/form-submission-exports/{id}/part:
    get:
      x-seedly-oauth-scope: "forms:read"
      x-seedly-standard-scope: "forms:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getFormSubmissionExportsIdPart"
      tags: ["Forms"]
      summary: "GET /api/v1/form-submission-exports/{id}/part"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Returns one stored part of a complete export, at most 512 KiB, addressed by zero-based part number. Each download is audited."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"part","in":"query","schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/form-submission-exports/{id}/resume:
    post:
      x-seedly-oauth-scope: "forms:read"
      x-seedly-standard-scope: "forms:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postFormSubmissionExportsIdResume"
      tags: ["Forms"]
      summary: "POST /api/v1/form-submission-exports/{id}/resume"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Resumes a paused or stalled export. Status is visible only to the starting credential. Each batch rechecks authority; revocation pauses work and completed batches stay in place. Resume adopts the current verified credential."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/form-submission-exports/{id}/cancel:
    post:
      x-seedly-oauth-scope: "forms:read"
      x-seedly-standard-scope: "forms:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postFormSubmissionExportsIdCancel"
      tags: ["Forms"]
      summary: "POST /api/v1/form-submission-exports/{id}/cancel"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Cancels an export and removes stored parts. Status is visible only to the starting credential. Each batch rechecks authority; revocation pauses work and completed batches stay in place. Resume adopts the current verified credential."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/form-folders/{id}/deletion-jobs:
    post:
      x-seedly-oauth-scope: "forms:delete"
      x-seedly-standard-scope: "forms:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postFormFoldersIdDeletionJobs"
      tags: ["Forms"]
      summary: "POST /api/v1/form-folders/{id}/deletion-jobs"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Moves any number of contained forms and child folders to root in batches of 25, then removes the folder only after both are empty. Status is visible only to the starting credential. Each batch rechecks authority; revocation pauses work and completed batches stay in place. Resume adopts the current verified credential."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/form-folder-deletions/{id}:
    get:
      x-seedly-oauth-scope: "forms:delete"
      x-seedly-standard-scope: "forms:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getFormFolderDeletionsId"
      tags: ["Forms"]
      summary: "GET /api/v1/form-folder-deletions/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Reads folder deletion progress. Status is visible only to the starting credential. Each batch rechecks authority; revocation pauses work and completed batches stay in place. Resume adopts the current verified credential."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/form-folder-deletions/{id}/resume:
    post:
      x-seedly-oauth-scope: "forms:delete"
      x-seedly-standard-scope: "forms:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postFormFolderDeletionsIdResume"
      tags: ["Forms"]
      summary: "POST /api/v1/form-folder-deletions/{id}/resume"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Status is visible only to the starting credential. Each batch rechecks authority; revocation pauses work and completed batches stay in place. Resume adopts the current verified credential."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/form-folder-deletions/{id}/cancel:
    post:
      x-seedly-oauth-scope: "forms:delete"
      x-seedly-standard-scope: "forms:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postFormFolderDeletionsIdCancel"
      tags: ["Forms"]
      summary: "POST /api/v1/form-folder-deletions/{id}/cancel"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Status is visible only to the starting credential. Each batch rechecks authority; revocation pauses work and completed batches stay in place. Resume adopts the current verified credential."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/form-submissions/{id}/release:
    post:
      x-seedly-oauth-scope: "forms:moderate"
      x-seedly-standard-scope: "forms:moderate"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postFormSubmissionsIdRelease"
      tags: ["Forms"]
      summary: "POST /api/v1/form-submissions/{id}/release"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Also requires forms:read, contacts:read and contacts:write; a held booking also requires appointments:write. Runs the same path as a native operator release, including contact updates, bookings, consent handling, notifications and workflows. A replay returns the original receipt with no second effect. An already released submission conflicts. Refused for test credentials."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/call-search:
    get:
      x-seedly-oauth-scope: "call-history:read"
      x-seedly-standard-scope: "call-history:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getCallSearch"
      tags: ["Calls"]
      summary: "GET /api/v1/call-search"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Also requires contacts:read. Filters calls by contact, direction, outcome, exact phone number and time range. Pages read at most 50 rows, so a page can be empty while hasMore is true. Calls older than one year are unavailable."
      parameters: [{"name":"contactId","in":"query","schema":{"type":"string"}},{"name":"direction","in":"query","schema":{"type":"string"}},{"name":"outcome","in":"query","schema":{"type":"string"}},{"name":"phone","in":"query","schema":{"type":"string"}},{"name":"from","in":"query","schema":{"type":"string"}},{"name":"to","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/call-metrics:
    get:
      x-seedly-oauth-scope: "call-history:read"
      x-seedly-standard-scope: "call-history:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getCallMetrics"
      tags: ["Calls"]
      summary: "GET /api/v1/call-metrics"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Also requires contacts:read. Aggregate call counts, talk time, outcomes, dispositions, sources and a daily series for a range of at most 400 days, in the location timezone. truncated means more than 10000 calls matched. Per-rep figures are not included."
      parameters: [{"name":"from","in":"query","schema":{"type":"string"}},{"name":"to","in":"query","schema":{"type":"string"}},{"name":"direction","in":"query","schema":{"type":"string"}},{"name":"outcome","in":"query","schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/calls/{id}/grade:
    get:
      x-seedly-oauth-scope: "calls:transcripts:read"
      x-seedly-standard-scope: "calls:transcripts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getCallsIdGrade"
      tags: ["Calls"]
      summary: "GET /api/v1/calls/{id}/grade"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Also requires call-history:read, calls:recordings:read and contacts:read. Returns the AI grade for a call."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/calls/{id}/disposition:
    patch:
      x-seedly-oauth-scope: "calls:disposition"
      x-seedly-standard-scope: "calls:disposition"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "patchCallsIdDisposition"
      tags: ["Calls"]
      summary: "PATCH /api/v1/calls/{id}/disposition"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Also requires call-history:read and contacts:read. Sets a configured outcome through the native command. A do-not-call outcome adds the number to the voice do-not-call list, and the call dispositioned workflow trigger fires."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["dispositionId"],"properties":{"dispositionId":{"type":"string"}}}}}}
  /api/v1/phone-numbers:
    get:
      x-seedly-oauth-scope: "phone-numbers:read"
      x-seedly-standard-scope: "phone-numbers:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getPhoneNumbers"
      tags: ["Phone numbers"]
      summary: "GET /api/v1/phone-numbers"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Lists numbers assigned to this location. Provider identifiers and credentials are not included."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/phone-numbers/{id}:
    get:
      x-seedly-oauth-scope: "phone-numbers:read"
      x-seedly-standard-scope: "phone-numbers:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getPhoneNumbersId"
      tags: ["Phone numbers"]
      summary: "GET /api/v1/phone-numbers/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Returns one number assigned to this location."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/phone-numbers/{id}/assignment:
    patch:
      x-seedly-oauth-scope: "phone-numbers:write"
      x-seedly-standard-scope: "phone-numbers:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "patchPhoneNumbersIdAssignment"
      tags: ["Phone numbers"]
      summary: "PATCH /api/v1/phone-numbers/{id}/assignment"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Also requires users:read. Assigns a number to a user with access to this location, or null for a shared number."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["userId"],"properties":{"userId":{"type":["string","null"]}}}}}}
  /api/v1/phone-numbers/reorder:
    post:
      x-seedly-oauth-scope: "phone-numbers:write"
      x-seedly-standard-scope: "phone-numbers:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postPhoneNumbersReorder"
      tags: ["Phone numbers"]
      summary: "POST /api/v1/phone-numbers/reorder"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Sets the order of every number in this location, which determines the primary outbound SMS number. The list must contain each number exactly once."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["orderedIds"],"properties":{"orderedIds":{"type":"array","minItems":1,"maxItems":500,"items":{"type":"string"}}}}}}}
  /api/v1/phone-numbers/{id}/configuration:
    patch:
      x-seedly-oauth-scope: "phone-numbers:admin"
      x-seedly-standard-scope: "phone-numbers:admin"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "patchPhoneNumbersIdConfiguration"
      tags: ["Phone numbers"]
      summary: "PATCH /api/v1/phone-numbers/{id}/configuration"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Also requires phone-numbers:read. Changes usage, call recording or key-to-connect for one number. Recording has legal consent consequences. Purchases, releases and paid anti-spam stay native."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"usage":{"type":"string","enum":["sms","voice","both","call_tracking"]},"recordCalls":{"type":"boolean"},"requireKeyToConnect":{"type":"boolean"}}}}}}
  /api/v1/dialer-sessions:
    get:
      x-seedly-oauth-scope: "dialer:read"
      x-seedly-standard-scope: "dialer:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getDialerSessions"
      tags: ["Dialer"]
      summary: "GET /api/v1/dialer-sessions"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Lists dialer sessions."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "dialer:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: "postDialerSessions"
      tags: ["Dialer"]
      summary: "POST /api/v1/dialer-sessions"
      description: "OAuth connections only, acting for the consenting user. Standard location keys are machine credentials with no rep, so they are refused. Legacy keys, CloseBot and own/team/selected grants are unsupported.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Also requires contacts:read. Creates a queue for the consenting user from either 1 to 500 contact IDs or a segmentId, never both. Nothing is dialed. A segment source also requires segments:read and the reads its rules need, such as opportunities:read for a pipeline stage rule, and is refused for a user limited to their own or their team's contacts. It uses the same evaluation as the app, leaves out contacts with no number that can be dialed, uses each contact's first valid number, and queues at most the first 500 that remain; audienceTruncated is true when more remained or the read stopped early. Voice do-not-call, DND, opt-out and the calling window are checked on the live contact at every claim, so queued does not mean callable."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["settings"],"properties":{"name":{"type":"string"},"contactIds":{"type":"array","minItems":1,"maxItems":500,"items":{"type":"string"}},"segmentId":{"type":"string"},"settings":{"type":"object"}}}}}}
  /api/v1/dialer-sessions/{id}:
    get:
      x-seedly-oauth-scope: "dialer:read"
      x-seedly-standard-scope: "dialer:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getDialerSessionsId"
      tags: ["Dialer"]
      summary: "GET /api/v1/dialer-sessions/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Returns dialer session progress."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/dialer-sessions/{id}/items:
    get:
      x-seedly-oauth-scope: "dialer:read"
      x-seedly-standard-scope: "dialer:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getDialerSessionsIdItems"
      tags: ["Dialer"]
      summary: "GET /api/v1/dialer-sessions/{id}/items"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Also requires contacts:read. Lists queue items in order, with phone numbers."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/dialer-sessions/{id}/pause:
    post:
      x-seedly-oauth-scope: "dialer:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: "postDialerSessionsIdPause"
      tags: ["Dialer"]
      summary: "POST /api/v1/dialer-sessions/{id}/pause"
      description: "OAuth connections only, acting for the consenting user. Standard location keys are machine credentials with no rep, so they are refused. Legacy keys, CloseBot and own/team/selected grants are unsupported.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Pauses the user's own session."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/dialer-sessions/{id}/resume:
    post:
      x-seedly-oauth-scope: "dialer:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: "postDialerSessionsIdResume"
      tags: ["Dialer"]
      summary: "POST /api/v1/dialer-sessions/{id}/resume"
      description: "OAuth connections only, acting for the consenting user. Standard location keys are machine credentials with no rep, so they are refused. Legacy keys, CloseBot and own/team/selected grants are unsupported.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Resumes the user's own session."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/dialer-sessions/{id}/end:
    post:
      x-seedly-oauth-scope: "dialer:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: "postDialerSessionsIdEnd"
      tags: ["Dialer"]
      summary: "POST /api/v1/dialer-sessions/{id}/end"
      description: "OAuth connections only, acting for the consenting user. Standard location keys are machine credentials with no rep, so they are refused. Legacy keys, CloseBot and own/team/selected grants are unsupported.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Ends the user's own session."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/dialer-items/{id}/wrap-up:
    post:
      x-seedly-oauth-scope: "dialer:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: "postDialerItemsIdWrapUp"
      tags: ["Dialer"]
      summary: "POST /api/v1/dialer-items/{id}/wrap-up"
      description: "OAuth connections only, acting for the consenting user. Standard location keys are machine credentials with no rep, so they are refused. Legacy keys, CloseBot and own/team/selected grants are unsupported.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Moves a claimed item to wrap-up."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/dialer-items/{id}/complete:
    post:
      x-seedly-oauth-scope: "dialer:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: "postDialerItemsIdComplete"
      tags: ["Dialer"]
      summary: "POST /api/v1/dialer-items/{id}/complete"
      description: "OAuth connections only, acting for the consenting user. Standard location keys are machine credentials with no rep, so they are refused. Legacy keys, CloseBot and own/team/selected grants are unsupported.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Completes an item. A dispositionId also requires calls:disposition, because it can add the number to the do-not-call list and start workflows."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"dispositionId":{"type":"string"},"notes":{"type":"string","maxLength":16000}}}}}}
  /api/v1/dialer-items/{id}/skip:
    post:
      x-seedly-oauth-scope: "dialer:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: "postDialerItemsIdSkip"
      tags: ["Dialer"]
      summary: "POST /api/v1/dialer-items/{id}/skip"
      description: "OAuth connections only, acting for the consenting user. Standard location keys are machine credentials with no rep, so they are refused. Legacy keys, CloseBot and own/team/selected grants are unsupported.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Skips an item. The location's required-outcome rule applies."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/dialer-items/{id}/release:
    post:
      x-seedly-oauth-scope: "dialer:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: "postDialerItemsIdRelease"
      tags: ["Dialer"]
      summary: "POST /api/v1/dialer-items/{id}/release"
      description: "OAuth connections only, acting for the consenting user. Standard location keys are machine credentials with no rep, so they are refused. Legacy keys, CloseBot and own/team/selected grants are unsupported.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Returns a claimed item when the softphone could not place the call, and refunds the daily cap slot."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/dialer-sessions/{id}/claim-next:
    post:
      x-seedly-oauth-scope: "dialer:outbound"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: "postDialerSessionsIdClaimNext"
      tags: ["Dialer"]
      summary: "POST /api/v1/dialer-sessions/{id}/claim-next"
      description: "OAuth connections only, acting for the consenting user. Standard location keys are machine credentials with no rep, so they are refused. Legacy keys, CloseBot and own/team/selected grants are unsupported.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Also requires dialer:read and contacts:read. Applies native do-not-call, calling window and daily cap rules, creates the call log and returns the number for the rep's softphone. The call itself is placed by the softphone, not by this API."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/social-planner/posts:
    get:
      x-seedly-oauth-scope: "social-posts:read"
      x-seedly-standard-scope: "social-posts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getSocialPlannerPosts"
      tags: ["Social"]
      summary: "GET /api/v1/social-planner/posts"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Lists social posts as metadata. Provider identifiers and media storage references are not included."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "social-posts:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: "postSocialPlannerPosts"
      tags: ["Social"]
      summary: "POST /api/v1/social-planner/posts"
      description: "OAuth connections only, because a draft records its author and a machine key is not one. Standard keys, legacy keys, CloseBot and own/team/selected grants are unsupported. Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Creates a draft. Nothing is sent to a social network. Media is not accepted here."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"platforms":{"type":"array","minItems":1,"maxItems":20,"items":{"type":"string"}},"content":{"type":"string","maxLength":20000},"title":{"type":"string","maxLength":500},"firstComment":{"type":"string","maxLength":2200},"contentType":{"type":"string"}}}}}}
  /api/v1/social-planner/posts/{id}:
    get:
      x-seedly-oauth-scope: "social-posts:read"
      x-seedly-standard-scope: "social-posts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getSocialPlannerPostsId"
      tags: ["Social"]
      summary: "GET /api/v1/social-planner/posts/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Returns post content and approval state."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
    patch:
      x-seedly-oauth-scope: "social-posts:write"
      x-seedly-standard-scope: "social-posts:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "patchSocialPlannerPostsId"
      tags: ["Social"]
      summary: "PATCH /api/v1/social-planner/posts/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Edits a draft. Scheduled, pending and published posts are edited in the app."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"platforms":{"type":"array","minItems":1,"maxItems":20,"items":{"type":"string"}},"content":{"type":"string","maxLength":20000},"title":{"type":"string","maxLength":500},"firstComment":{"type":"string","maxLength":2200},"contentType":{"type":"string"}}}}}}
    delete:
      x-seedly-oauth-scope: "social-posts:delete"
      x-seedly-standard-scope: "social-posts:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "deleteSocialPlannerPostsId"
      tags: ["Social"]
      summary: "DELETE /api/v1/social-planner/posts/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Deletes the post through the native command. A post already live on a network stays live there."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/social-planner/posts/{id}/contacts:
    get:
      x-seedly-oauth-scope: "social-posts:read"
      x-seedly-standard-scope: "social-posts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getSocialPlannerPostContacts"
      tags: ["Social Planner"]
      summary: "GET /api/v1/social-planner/posts/{id}/contacts"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Also requires contacts:read. Returns the ids of live linked contacts only."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Linked ids.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["id","contactIds"],"properties":{"id":{"type":"string"},"contactIds":{"type":"array","maxItems":200,"items":{"type":"string"}}}}}}}}},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"The stored links exceed the read limit."}}
    put:
      x-seedly-oauth-scope: "social-posts:write"
      x-seedly-standard-scope: "social-posts:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "putSocialPlannerPostContacts"
      tags: ["Social Planner"]
      summary: "PUT /api/v1/social-planner/posts/{id}/contacts"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Also requires contacts:read. Replaces the contacts linked to a post with at most 100 live contacts in this location. An empty list clears them. Links are CRM context: nothing is sent or published."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["contactIds"],"properties":{"contactIds":{"type":"array","maxItems":100,"items":{"type":"string"}}}}}}}
  /api/v1/social-planner/posts/{id}/opportunities:
    get:
      x-seedly-oauth-scope: "social-posts:read"
      x-seedly-standard-scope: "social-posts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getSocialPlannerPostOpportunities"
      tags: ["Social Planner"]
      summary: "GET /api/v1/social-planner/posts/{id}/opportunities"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Also requires opportunities:read. Returns the ids of live linked opportunities only, and for OAuth only those in pipelines the user can see."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Linked ids.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["id","dealIds","complete"],"properties":{"id":{"type":"string"},"dealIds":{"type":"array","maxItems":200,"items":{"type":"string"}},"complete":{"type":"boolean","description":"False when a linked opportunity sits in a pipeline hidden from the OAuth user."}}}}}}}},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"The stored links exceed the read limit."}}
    put:
      x-seedly-oauth-scope: "social-posts:write"
      x-seedly-standard-scope: "social-posts:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "putSocialPlannerPostOpportunities"
      tags: ["Social Planner"]
      summary: "PUT /api/v1/social-planner/posts/{id}/opportunities"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Also requires opportunities:read, and for OAuth access to each opportunity's pipeline. Replaces the opportunities linked to a post with at most 100 live opportunities in this location. An empty list clears them. Links are CRM context: nothing is sent or published."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["dealIds"],"properties":{"dealIds":{"type":"array","maxItems":100,"items":{"type":"string"}}}}}}}
  /api/v1/social-planner/queue/next-slot:
    get:
      x-seedly-oauth-scope: "social-posts:read"
      x-seedly-standard-scope: "social-posts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getSocialPlannerQueueNextSlot"
      tags: ["Social Planner"]
      summary: "GET /api/v1/social-planner/queue/next-slot"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Returns the next active queue slot in the location's timezone as nextSlot, or null when none is active. Read only: it does not schedule or hold anything. Stored slots with an invalid day or time are skipped. A queue above 500 slots, or a location with an invalid stored timezone, returns 409."
      parameters: []
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/social-planner/queue:
    get:
      x-seedly-oauth-scope: "social-posts:read"
      x-seedly-standard-scope: "social-posts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getSocialPlannerQueue"
      tags: ["Social"]
      summary: "GET /api/v1/social-planner/queue"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Lists posting queue slots."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "social-posts:write"
      x-seedly-standard-scope: "social-posts:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postSocialPlannerQueue"
      tags: ["Social"]
      summary: "POST /api/v1/social-planner/queue"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Adds a queue slot."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"dayOfWeek":{"type":"integer","minimum":0,"maximum":6},"time":{"type":"string"},"timezone":{"type":"string"},"isActive":{"type":"boolean"}}}}}}
  /api/v1/social-planner/follower-history:
    get:
      x-seedly-oauth-scope: "social-posts:read"
      x-seedly-standard-scope: "social-posts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getSocialPlannerFollowerHistory"
      tags: ["Social"]
      summary: "GET /api/v1/social-planner/follower-history"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes. Returns stored daily follower counts per platform. Provider analytics responses stay in the app."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"from","in":"query","schema":{"type":"string"}},{"name":"to","in":"query","schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/social-planner/posts/{id}/submit:
    post:
      x-seedly-oauth-scope: "social-posts:write"
      x-seedly-standard-scope: "social-posts:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postSocialPlannerPostsIdSubmit"
      tags: ["Social"]
      summary: "POST /api/v1/social-planner/posts/{id}/submit"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Submits a draft for approval."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"note":{"type":"string","maxLength":2000}}}}}}
  /api/v1/social-planner/queue/{id}:
    patch:
      x-seedly-oauth-scope: "social-posts:write"
      x-seedly-standard-scope: "social-posts:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "patchSocialPlannerQueueId"
      tags: ["Social"]
      summary: "PATCH /api/v1/social-planner/queue/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Edits a queue slot."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"dayOfWeek":{"type":"integer","minimum":0,"maximum":6},"time":{"type":"string"},"timezone":{"type":"string"},"isActive":{"type":"boolean"}}}}}}
    delete:
      x-seedly-oauth-scope: "social-posts:delete"
      x-seedly-standard-scope: "social-posts:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "deleteSocialPlannerQueueId"
      tags: ["Social"]
      summary: "DELETE /api/v1/social-planner/queue/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Deletes a queue slot."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/social-planner/posts/{id}/approve:
    post:
      x-seedly-oauth-scope: "social-posts:approve"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: "postSocialPlannerPostsIdApprove"
      tags: ["Social"]
      summary: "POST /api/v1/social-planner/posts/{id}/approve"
      description: "App publishing and scheduling are held until live provider acceptance; the permission alone does not enable them. OAuth connections only, because an approval records a person. Legacy keys, CloseBot and own/team/selected grants are unsupported.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Approves a pending post. Approving a post with a scheduled time also requires social-posts:publish, because it goes to the network."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"note":{"type":"string","maxLength":2000}}}}}}
  /api/v1/social-planner/posts/{id}/reject:
    post:
      x-seedly-oauth-scope: "social-posts:approve"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: "postSocialPlannerPostsIdReject"
      tags: ["Social"]
      summary: "POST /api/v1/social-planner/posts/{id}/reject"
      description: "OAuth connections only, because an approval records a person. Legacy keys, CloseBot and own/team/selected grants are unsupported.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Rejects a pending post. A note is required."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"note":{"type":"string","maxLength":2000}}}}}}
  /api/v1/social-planner/posts/{id}/publish:
    post:
      x-seedly-oauth-scope: "social-posts:publish"
      x-seedly-standard-scope: "social-posts:publish"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postSocialPlannerPostsIdPublish"
      tags: ["Social"]
      summary: "POST /api/v1/social-planner/posts/{id}/publish"
      description: "App publishing and scheduling are held until live provider acceptance; the permission alone does not enable them. Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Also requires social-posts:read. Publishes a draft or failed post now through the native path. Posts waiting for approval are refused. Never retry with a new key. Refused with 409 while a scheduled send is still in flight, or when its delivery could not be confirmed: that post is retried by a person in the app."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/social-planner/posts/{id}/retry:
    post:
      x-seedly-oauth-scope: "social-posts:publish"
      x-seedly-standard-scope: "social-posts:publish"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postSocialPlannerPostsIdRetry"
      tags: ["Social"]
      summary: "POST /api/v1/social-planner/posts/{id}/retry"
      description: "App publishing and scheduling are held until live provider acceptance; the permission alone does not enable them. Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Also requires social-posts:read. Retries a failed or partial post through the native path, only on platforms that failed. Refused with 409 while a scheduled send is still in flight, or when its delivery could not be confirmed: that post is retried by a person in the app."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/social-planner/posts/{id}/schedule:
    post:
      x-seedly-oauth-scope: "social-posts:publish"
      x-seedly-standard-scope: "social-posts:publish"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postSocialPlannerPostsIdSchedule"
      tags: ["Social"]
      summary: "POST /api/v1/social-planner/posts/{id}/schedule"
      description: "App publishing and scheduling are held until live provider acceptance; the permission alone does not enable them. Schedule a draft post for future dispatch. The post is held locally and NOT sent to the provider until the scheduled time. Also requires the publish operation and social-posts:read. The original credential is reauthorized at dispatch and again immediately before each provider send; if it has lost access the post becomes failed for a person to review. Provider acceptance is confirmed only by the post status. A Standard key can only schedule a post with a real author. Requires Idempotency-Key."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Schedule receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing approval."},"404":{"description":"Post unavailable."},"409":{"description":"Idempotency or state conflict."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","required":["scheduledAt"],"properties":{"scheduledAt":{"type":"number","description":"Epoch ms when the post should be dispatched."}}}}}}
  /api/v1/social-planner/posts/{id}/unschedule:
    post:
      x-seedly-oauth-scope: "social-posts:write"
      x-seedly-standard-scope: "social-posts:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "postSocialPlannerPostsIdUnschedule"
      tags: ["Social"]
      summary: "POST /api/v1/social-planner/posts/{id}/unschedule"
      description: "Unschedule a post this credential scheduled, returning it to draft. Staff schedules and schedules held by another credential are refused. Requires Idempotency-Key."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Unschedule receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing approval or ownership."},"404":{"description":"Post unavailable."},"409":{"description":"Idempotency or state conflict."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
  /api/v1/social-planner/posts/{id}/scheduled:
    patch:
      x-seedly-oauth-scope: "social-posts:write"
      x-seedly-standard-scope: "social-posts:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "patchSocialPlannerPostsIdScheduled"
      tags: ["Social"]
      summary: "PATCH /api/v1/social-planner/posts/{id}/scheduled"
      description: "App publishing and scheduling are held until live provider acceptance; the permission alone does not enable them. Edit a draft, or a post this credential scheduled. Staff schedules and schedules held by another credential are refused. Moving scheduledAt also requires social-posts:publish and only applies to a scheduled post. A Standard key can only edit a post with a real author. Clears earlier approval status. Requires Idempotency-Key."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Edit receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing approval or ownership."},"404":{"description":"Post unavailable."},"409":{"description":"Idempotency or state conflict."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"content":{"type":"string"},"scheduledAt":{"type":"number"}}}}}}
  /api/v1/social-planner/analytics:
    get:
      x-seedly-oauth-scope: "social-posts:read"
      x-seedly-standard-scope: "social-posts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getSocialPlannerAnalytics"
      tags: ["Social"]
      summary: "GET /api/v1/social-planner/analytics"
      description: "Safe bounded analytics projection. Filters provider secrets from stored snapshots. Supports cursor-based pagination."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"platform","in":"query","schema":{"type":"string"}},{"name":"from","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","schema":{"type":"string","format":"date-time"}}]
      responses: {"200":{"description":"Analytics projection.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"type":"object"}}}}}},"400":{"description":"Invalid parameters."},"401":{"description":"Invalid credential."},"403":{"description":"Missing approval."}}
  /api/v1/forms:
    get:
      x-seedly-oauth-scope: "forms:read"
      x-seedly-standard-scope: "forms:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "listForms"
      summary: "listForms"
      tags: ["Forms"]
      description: "New location-wide Standard v2 or OAuth operation approval only. Legacy keys, CloseBot and restricted record grants cannot enter these operations. Uses native form configuration and same-tenant parent validation."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":8192}}]
      responses: {"200":{"description":"Safe projection or minimal durable receipt.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/FormDefinition"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}},"required":["data","meta"]}}}},"400":{"description":"Invalid configuration, unsupported cursor or request limit exceeded."},"401":{"description":"Missing, expired or invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported approval."},"404":{"description":"Record, live parent or attachment proof unavailable."},"409":{"description":"Idempotency conflict or signed-submission confirmation required."},"413":{"description":"Request or attachment exceeds its byte limit."},"415":{"description":"Unsupported request or attachment MIME type."},"416":{"description":"Attachment Range requests are unsupported."},"429":{"description":"Rate or audit budget exceeded."}}
    post:
      x-seedly-oauth-scope: "forms:write"
      x-seedly-standard-scope: "forms:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "createForm"
      summary: "createForm"
      tags: ["Forms"]
      description: "New location-wide Standard v2 or OAuth operation approval only. Legacy keys, CloseBot and restricted record grants cannot enter these operations. Stable Idempotency-Key required; retries recheck live authority and parent/source proofs. Uses native form configuration and same-tenant parent validation."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or minimal durable receipt.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"created":{"const":true}},"required":["id","created"]}},"required":["data"]}}}},"400":{"description":"Invalid configuration, unsupported cursor or request limit exceeded."},"401":{"description":"Missing, expired or invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported approval."},"404":{"description":"Record, live parent or attachment proof unavailable."},"409":{"description":"Idempotency conflict or signed-submission confirmation required."},"413":{"description":"Request or attachment exceeds its byte limit."},"415":{"description":"Unsupported request or attachment MIME type."},"416":{"description":"Attachment Range requests are unsupported."},"429":{"description":"Rate or audit budget exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormCreate"}}}}
  /api/v1/forms/{id}:
    get:
      x-seedly-oauth-scope: "forms:read"
      x-seedly-standard-scope: "forms:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getForm"
      summary: "getForm"
      tags: ["Forms"]
      description: "New location-wide Standard v2 or OAuth operation approval only. Legacy keys, CloseBot and restricted record grants cannot enter these operations. Uses native form configuration and same-tenant parent validation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe projection or minimal durable receipt.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"data":{"$ref":"#/components/schemas/FormDefinition"}},"required":["data"]}}}},"400":{"description":"Invalid configuration, unsupported cursor or request limit exceeded."},"401":{"description":"Missing, expired or invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported approval."},"404":{"description":"Record, live parent or attachment proof unavailable."},"409":{"description":"Idempotency conflict or signed-submission confirmation required."},"413":{"description":"Request or attachment exceeds its byte limit."},"415":{"description":"Unsupported request or attachment MIME type."},"416":{"description":"Attachment Range requests are unsupported."},"429":{"description":"Rate or audit budget exceeded."}}
    patch:
      x-seedly-oauth-scope: "forms:write"
      x-seedly-standard-scope: "forms:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "updateForm"
      summary: "updateForm"
      tags: ["Forms"]
      description: "New location-wide Standard v2 or OAuth operation approval only. Legacy keys, CloseBot and restricted record grants cannot enter these operations. Stable Idempotency-Key required; retries recheck live authority and parent/source proofs. Updates native form fields, pages, theme and allowlisted presentation settings. Maximum 512 KiB JSON, 200 fields, 50 pages/steps, 100 success elements. Native HTML sanitization and scoped CSS sanitization apply. Contact/opportunity custom-field and list references require matching source reads and live tenant ownership. Existing secrets are preserved but cannot be read or supplied. Editing a published form additionally requires forms:publish and active automation dependencies. Accepted retries revalidate authority/dependencies without applying stale proposed field/page combinations."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or minimal durable receipt.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"updated":{"const":true}},"required":["id","updated"]}},"required":["data"]}}}},"400":{"description":"Invalid configuration, unsupported cursor or request limit exceeded."},"401":{"description":"Missing, expired or invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported approval."},"404":{"description":"Record, live parent or attachment proof unavailable."},"409":{"description":"Idempotency conflict or signed-submission confirmation required."},"413":{"description":"Request or attachment exceeds its byte limit."},"415":{"description":"Unsupported request or attachment MIME type."},"416":{"description":"Attachment Range requests are unsupported."},"429":{"description":"Rate or audit budget exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormUpdate"}}}}
  /api/v1/forms/{id}/delete:
    post:
      x-seedly-oauth-scope: "forms:delete"
      x-seedly-standard-scope: "forms:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "deleteForm"
      summary: "deleteForm"
      tags: ["Forms"]
      description: "New location-wide Standard v2 or OAuth operation approval only. Legacy keys, CloseBot and restricted record grants cannot enter these operations. Stable Idempotency-Key required; retries recheck live authority and parent/source proofs. Permanently deletes the form and its submissions with native bounded cleanup. Preference-center forms cannot be deleted. If signed submissions exist, returns 409 VALIDATION_ERROR with details.reason=SIGNED_SUBMISSIONS_PRESENT, count, capped and confirmationNumber. Retry with that exact current confirmationNumber. The confirmation gate runs before any blob deletion. Use a new Idempotency-Key after changing the confirmation payload."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or minimal durable receipt.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"deleted":{"const":true}},"required":["id","deleted"]}},"required":["data"]}}}},"400":{"description":"Invalid configuration, unsupported cursor or request limit exceeded."},"401":{"description":"Missing, expired or invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported approval."},"404":{"description":"Record, live parent or attachment proof unavailable."},"409":{"description":"Idempotency conflict or signed-submission confirmation required."},"413":{"description":"Request or attachment exceeds its byte limit."},"415":{"description":"Unsupported request or attachment MIME type."},"416":{"description":"Attachment Range requests are unsupported."},"429":{"description":"Rate or audit budget exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormDelete"}}}}
  /api/v1/forms/{id}/submissions:
    get:
      x-seedly-oauth-scope: "forms:read"
      x-seedly-standard-scope: "forms:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "listFormSubmissions"
      summary: "listFormSubmissions"
      tags: ["Forms"]
      description: "New location-wide Standard v2 or OAuth operation approval only. Legacy keys, CloseBot and restricted record grants cannot enter these operations. Requires independently approved contacts:read. Insertion-time descending cursor pagination; foreign/missing contact parents and expired unsigned rows are skipped without dropping continuation. Native HIPAA view audit occurs before response. Answers preserve historical scalar/array/flat-matrix values after schema edits, excluding reserved metadata and storage references. Attachments contain only field identifiers."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":8192}}]
      responses: {"200":{"description":"Safe projection or minimal durable receipt.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/FormSubmission"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}},"required":["data","meta"]}}}},"400":{"description":"Invalid configuration, unsupported cursor or request limit exceeded."},"401":{"description":"Missing, expired or invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported approval."},"404":{"description":"Record, live parent or attachment proof unavailable."},"409":{"description":"Idempotency conflict or signed-submission confirmation required."},"413":{"description":"Request or attachment exceeds its byte limit."},"415":{"description":"Unsupported request or attachment MIME type."},"416":{"description":"Attachment Range requests are unsupported."},"429":{"description":"Rate or audit budget exceeded."}}
  /api/v1/form-submissions/{id}:
    get:
      x-seedly-oauth-scope: "forms:read"
      x-seedly-standard-scope: "forms:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getFormSubmission"
      summary: "getFormSubmission"
      tags: ["Forms"]
      description: "New location-wide Standard v2 or OAuth operation approval only. Legacy keys, CloseBot and restricted record grants cannot enter these operations. Requires independently approved contacts:read. Returns safe answers and attachment selectors without IPs, fingerprints, visitor tokens, raw quarantine payloads, storage IDs or URLs. Native HIPAA view audit and unsigned retention checks apply."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe projection or minimal durable receipt.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"data":{"$ref":"#/components/schemas/FormSubmission"}},"required":["data"]}}}},"400":{"description":"Invalid configuration, unsupported cursor or request limit exceeded."},"401":{"description":"Missing, expired or invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported approval."},"404":{"description":"Record, live parent or attachment proof unavailable."},"409":{"description":"Idempotency conflict or signed-submission confirmation required."},"413":{"description":"Request or attachment exceeds its byte limit."},"415":{"description":"Unsupported request or attachment MIME type."},"416":{"description":"Attachment Range requests are unsupported."},"429":{"description":"Rate or audit budget exceeded."}}
  /api/v1/forms/{id}/analytics:
    get:
      x-seedly-oauth-scope: "forms:read"
      x-seedly-standard-scope: "forms:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getFormAnalytics"
      summary: "getFormAnalytics"
      tags: ["Forms"]
      description: "New location-wide Standard v2 or OAuth operation approval only. Legacy keys, CloseBot and restricted record grants cannot enter these operations. Requires contacts:read. Reuses the native bounded aggregation and sharded view counter. submissionsOverTimePartial explicitly marks an incomplete 30-day window; avgCompletionMs may be null."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe projection or minimal durable receipt.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"data":{"$ref":"#/components/schemas/FormAnalytics"}},"required":["data"]}}}},"400":{"description":"Invalid configuration, unsupported cursor or request limit exceeded."},"401":{"description":"Missing, expired or invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported approval."},"404":{"description":"Record, live parent or attachment proof unavailable."},"409":{"description":"Idempotency conflict or signed-submission confirmation required."},"413":{"description":"Request or attachment exceeds its byte limit."},"415":{"description":"Unsupported request or attachment MIME type."},"416":{"description":"Attachment Range requests are unsupported."},"429":{"description":"Rate or audit budget exceeded."}}
  /api/v1/form-submissions/{id}/attachment:
    get:
      x-seedly-oauth-scope: "forms:read"
      x-seedly-standard-scope: "forms:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "downloadFormAttachment"
      summary: "downloadFormAttachment"
      tags: ["Forms"]
      description: "New location-wide Standard v2 or OAuth operation approval only. Legacy keys, CloseBot and restricted record grants cannot enter these operations. Requires forms:read plus contacts:read, live same-tenant submission/form/contact proof and native HIPAA download audit. fieldId is the uploaded-file/signature answer key, or signed-copy for the signed PDF. Returns authenticated bytes only, never a storage, visitor or data URL. Stored files/PDFs require same-tenant nonconflicted ownership-ledger proof and are limited to 10 MiB. Inline PNG/JPEG signatures are limited to 2 MiB encoded input. Unsigned expired submissions are unavailable; native signed retention exemption applies. All Range requests return 416. Responses use attachment disposition, private no-store, nosniff and sandbox CSP."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"fieldId","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":200},"description":"Answer field ID or signed-copy."}]
      responses: {"200":{"description":"Requires forms:read plus contacts:read, live same-tenant submission/form/contact proof and native HIPAA download audit. fieldId is the uploaded-file/signature answer key, or signed-copy for the signed PDF. Returns authenticated bytes only, never a storage, visitor or data URL. Stored files/PDFs require same-tenant nonconflicted ownership-ledger proof and are limited to 10 MiB. Inline PNG/JPEG signatures are limited to 2 MiB encoded input. Unsigned expired submissions are unavailable; native signed retention exemption applies. All Range requests return 416. Responses use attachment disposition, private no-store, nosniff and sandbox CSP.","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}},"application/pdf":{"schema":{"type":"string","format":"binary"}},"image/png":{"schema":{"type":"string","format":"binary"}},"image/jpeg":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Invalid configuration, unsupported cursor or request limit exceeded."},"401":{"description":"Missing, expired or invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported approval."},"404":{"description":"Record, live parent or attachment proof unavailable."},"409":{"description":"Idempotency conflict or signed-submission confirmation required."},"413":{"description":"Request or attachment exceeds its byte limit."},"415":{"description":"Unsupported request or attachment MIME type."},"416":{"description":"Attachment Range requests are unsupported."},"429":{"description":"Rate or audit budget exceeded."}}
  /api/v1/form-folders:
    get:
      x-seedly-oauth-scope: "forms:read"
      x-seedly-standard-scope: "forms:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "listFormFolders"
      summary: "listFormFolders"
      tags: ["Forms"]
      description: "New location-wide Standard v2 or OAuth operation approval only. Legacy keys, CloseBot and restricted record grants cannot enter these operations. Uses native form configuration and same-tenant parent validation."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":8192}}]
      responses: {"200":{"description":"Safe projection or minimal durable receipt.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/FormFolder"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}},"required":["data","meta"]}}}},"400":{"description":"Invalid configuration, unsupported cursor or request limit exceeded."},"401":{"description":"Missing, expired or invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported approval."},"404":{"description":"Record, live parent or attachment proof unavailable."},"409":{"description":"Idempotency conflict or signed-submission confirmation required."},"413":{"description":"Request or attachment exceeds its byte limit."},"415":{"description":"Unsupported request or attachment MIME type."},"416":{"description":"Attachment Range requests are unsupported."},"429":{"description":"Rate or audit budget exceeded."}}
    post:
      x-seedly-oauth-scope: "forms:write"
      x-seedly-standard-scope: "forms:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "createFormFolder"
      summary: "createFormFolder"
      tags: ["Forms"]
      description: "New location-wide Standard v2 or OAuth operation approval only. Legacy keys, CloseBot and restricted record grants cannot enter these operations. Stable Idempotency-Key required; retries recheck live authority and parent/source proofs. Uses native form configuration and same-tenant parent validation."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or minimal durable receipt.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"created":{"const":true}},"required":["id","created"]}},"required":["data"]}}}},"400":{"description":"Invalid configuration, unsupported cursor or request limit exceeded."},"401":{"description":"Missing, expired or invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported approval."},"404":{"description":"Record, live parent or attachment proof unavailable."},"409":{"description":"Idempotency conflict or signed-submission confirmation required."},"413":{"description":"Request or attachment exceeds its byte limit."},"415":{"description":"Unsupported request or attachment MIME type."},"416":{"description":"Attachment Range requests are unsupported."},"429":{"description":"Rate or audit budget exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormFolderCreate"}}}}
  /api/v1/form-folders/{id}:
    get:
      x-seedly-oauth-scope: "forms:read"
      x-seedly-standard-scope: "forms:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getFormFolder"
      summary: "getFormFolder"
      tags: ["Forms"]
      description: "New location-wide Standard v2 or OAuth operation approval only. Legacy keys, CloseBot and restricted record grants cannot enter these operations. Uses native form configuration and same-tenant parent validation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe projection or minimal durable receipt.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"data":{"$ref":"#/components/schemas/FormFolder"}},"required":["data"]}}}},"400":{"description":"Invalid configuration, unsupported cursor or request limit exceeded."},"401":{"description":"Missing, expired or invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported approval."},"404":{"description":"Record, live parent or attachment proof unavailable."},"409":{"description":"Idempotency conflict or signed-submission confirmation required."},"413":{"description":"Request or attachment exceeds its byte limit."},"415":{"description":"Unsupported request or attachment MIME type."},"416":{"description":"Attachment Range requests are unsupported."},"429":{"description":"Rate or audit budget exceeded."}}
    patch:
      x-seedly-oauth-scope: "forms:write"
      x-seedly-standard-scope: "forms:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "updateFormFolder"
      summary: "updateFormFolder"
      tags: ["Forms"]
      description: "New location-wide Standard v2 or OAuth operation approval only. Legacy keys, CloseBot and restricted record grants cannot enter these operations. Stable Idempotency-Key required; retries recheck live authority and parent/source proofs. Uses native form configuration and same-tenant parent validation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or minimal durable receipt.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"updated":{"const":true}},"required":["id","updated"]}},"required":["data"]}}}},"400":{"description":"Invalid configuration, unsupported cursor or request limit exceeded."},"401":{"description":"Missing, expired or invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported approval."},"404":{"description":"Record, live parent or attachment proof unavailable."},"409":{"description":"Idempotency conflict or signed-submission confirmation required."},"413":{"description":"Request or attachment exceeds its byte limit."},"415":{"description":"Unsupported request or attachment MIME type."},"416":{"description":"Attachment Range requests are unsupported."},"429":{"description":"Rate or audit budget exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormFolderUpdate"}}}}
    delete:
      x-seedly-oauth-scope: "forms:delete"
      x-seedly-standard-scope: "forms:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "deleteFormFolder"
      summary: "deleteFormFolder"
      tags: ["Forms"]
      description: "New location-wide Standard v2 or OAuth operation approval only. Legacy keys, CloseBot and restricted record grants cannot enter these operations. Stable Idempotency-Key required; retries recheck live authority and parent/source proofs. Moves all forms and child folders to root using the native command. Request is rejected before mutation if either directory exceeds 1000 children or 2 MB, or contains foreign-tenant references; no silent truncation. Native UI behavior for larger historical directories remains unchanged."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or minimal durable receipt.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"deleted":{"const":true}},"required":["id","deleted"]}},"required":["data"]}}}},"400":{"description":"Invalid configuration, unsupported cursor or request limit exceeded."},"401":{"description":"Missing, expired or invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported approval."},"404":{"description":"Record, live parent or attachment proof unavailable."},"409":{"description":"Idempotency conflict or signed-submission confirmation required."},"413":{"description":"Request or attachment exceeds its byte limit."},"415":{"description":"Unsupported request or attachment MIME type."},"416":{"description":"Attachment Range requests are unsupported."},"429":{"description":"Rate or audit budget exceeded."}}
  /api/v1/forms/{id}/folder:
    patch:
      x-seedly-oauth-scope: "forms:write"
      x-seedly-standard-scope: "forms:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "moveFormToFolder"
      summary: "moveFormToFolder"
      tags: ["Forms"]
      description: "New location-wide Standard v2 or OAuth operation approval only. Legacy keys, CloseBot and restricted record grants cannot enter these operations. Stable Idempotency-Key required; retries recheck live authority and parent/source proofs. Uses native form configuration and same-tenant parent validation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or minimal durable receipt.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"updated":{"const":true}},"required":["id","updated"]}},"required":["data"]}}}},"400":{"description":"Invalid configuration, unsupported cursor or request limit exceeded."},"401":{"description":"Missing, expired or invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported approval."},"404":{"description":"Record, live parent or attachment proof unavailable."},"409":{"description":"Idempotency conflict or signed-submission confirmation required."},"413":{"description":"Request or attachment exceeds its byte limit."},"415":{"description":"Unsupported request or attachment MIME type."},"416":{"description":"Attachment Range requests are unsupported."},"429":{"description":"Rate or audit budget exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["folderId"],"properties":{"folderId":{"type":["string","null"]}}}}}}
  /api/v1/forms/{id}/clone:
    post:
      x-seedly-oauth-scope: "forms:write"
      x-seedly-standard-scope: "forms:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "cloneForm"
      summary: "cloneForm"
      tags: ["Forms"]
      description: "New location-wide Standard v2 or OAuth operation approval only. Legacy keys, CloseBot and restricted record grants cannot enter these operations. Stable Idempotency-Key required; retries recheck live authority and parent/source proofs. Requires forms:write plus forms:read source approval. Native cloning creates a draft and resets counters. Preserved native-only automation/secret metadata remains unexposed; publication requires fresh source authorization."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or minimal durable receipt.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"created":{"const":true}},"required":["id","created"]}},"required":["data"]}}}},"400":{"description":"Invalid configuration, unsupported cursor or request limit exceeded."},"401":{"description":"Missing, expired or invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported approval."},"404":{"description":"Record, live parent or attachment proof unavailable."},"409":{"description":"Idempotency conflict or signed-submission confirmation required."},"413":{"description":"Request or attachment exceeds its byte limit."},"415":{"description":"Unsupported request or attachment MIME type."},"416":{"description":"Attachment Range requests are unsupported."},"429":{"description":"Rate or audit budget exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{},"required":[]}}}}
  /api/v1/forms/{id}/automation:
    get:
      x-seedly-oauth-scope: "forms:read"
      x-seedly-standard-scope: "forms:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getFormAutomation"
      summary: "getFormAutomation"
      tags: ["Forms"]
      description: "New location-wide Standard v2 or OAuth operation approval only. Legacy keys, CloseBot and restricted record grants cannot enter these operations. Requires forms:read plus contacts:read. Returns only the documented automation fields, excluding webhook URLs, CAPTCHA secrets, provider configuration and inactive template metadata."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Safe projection or minimal durable receipt.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"data":{"$ref":"#/components/schemas/FormAutomation"}},"required":["data"]}}}},"400":{"description":"Invalid configuration, unsupported cursor or request limit exceeded."},"401":{"description":"Missing, expired or invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported approval."},"404":{"description":"Record, live parent or attachment proof unavailable."},"409":{"description":"Idempotency conflict or signed-submission confirmation required."},"413":{"description":"Request or attachment exceeds its byte limit."},"415":{"description":"Unsupported request or attachment MIME type."},"416":{"description":"Attachment Range requests are unsupported."},"429":{"description":"Rate or audit budget exceeded."}}
    patch:
      x-seedly-oauth-scope: "forms:automation"
      x-seedly-standard-scope: "forms:automation"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "updateFormAutomation"
      summary: "updateFormAutomation"
      tags: ["Forms"]
      description: "New location-wide Standard v2 or OAuth operation approval only. Legacy keys, CloseBot and restricted record grants cannot enter these operations. Stable Idempotency-Key required; retries recheck live authority and parent/source proofs. Requires explicit forms:automation consent, forms:read and contacts:read. This capability can configure up to 20 arbitrary external notification email recipients to receive future submission data. It is not implied by ordinary forms:write or messages:send. Configuration does not send immediately. Visitor follow-up, signed-copy and double-opt-in emails additionally require messages:send. Auto-created opportunities require opportunities:write plus pipelines:read and live pipeline edit authority. Double-opt-in list IDs must reference a same-location active manual list with contact-lists:read. Existing webhook activation requires webhooks:write and native URL validation; destination URL and secrets cannot be supplied. Published changes additionally require forms:publish. Native suppression, sending, rate and visitor-consent behavior remain authoritative."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or minimal durable receipt.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"updated":{"const":true}},"required":["id","updated"]}},"required":["data"]}}}},"400":{"description":"Invalid configuration, unsupported cursor or request limit exceeded."},"401":{"description":"Missing, expired or invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported approval."},"404":{"description":"Record, live parent or attachment proof unavailable."},"409":{"description":"Idempotency conflict or signed-submission confirmation required."},"413":{"description":"Request or attachment exceeds its byte limit."},"415":{"description":"Unsupported request or attachment MIME type."},"416":{"description":"Attachment Range requests are unsupported."},"429":{"description":"Rate or audit budget exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormAutomation"}}}}
  /api/v1/forms/{id}/publication:
    post:
      x-seedly-oauth-scope: "forms:publish"
      x-seedly-standard-scope: "forms:publish"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "setFormPublication"
      summary: "setFormPublication"
      tags: ["Forms"]
      description: "New location-wide Standard v2 or OAuth operation approval only. Legacy keys, CloseBot and restricted record grants cannot enter these operations. Stable Idempotency-Key required; retries recheck live authority and parent/source proofs. Requires forms:publish and its approved all-record form update authority. Publishing additionally requires forms:read, contacts:write, valid current definitions and all active automation source permissions; active automation requires forms:automation. Draft/archive transitions remove public availability. Does not execute a provider operation or submit a form."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or minimal durable receipt.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"updated":{"const":true}},"required":["id","updated"]}},"required":["data"]}}}},"400":{"description":"Invalid configuration, unsupported cursor or request limit exceeded."},"401":{"description":"Missing, expired or invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported approval."},"404":{"description":"Record, live parent or attachment proof unavailable."},"409":{"description":"Idempotency conflict or signed-submission confirmation required."},"413":{"description":"Request or attachment exceeds its byte limit."},"415":{"description":"Unsupported request or attachment MIME type."},"416":{"description":"Attachment Range requests are unsupported."},"429":{"description":"Rate or audit budget exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"status":{"enum":["draft","published","archived"]}},"required":["status"]}}}}
  /api/v1/forms/{id}/retention:
    patch:
      x-seedly-oauth-scope: "forms:delete"
      x-seedly-standard-scope: "forms:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "setFormRetention"
      summary: "setFormRetention"
      tags: ["Forms"]
      description: "New location-wide Standard v2 or OAuth operation approval only. Legacy keys, CloseBot and restricted record grants cannot enter these operations. Stable Idempotency-Key required; retries recheck live authority and parent/source proofs. Requires forms:delete plus the independently approved forms:write PATCH /api/v1/forms/:id operation. null retains indefinitely; otherwise an integer 1-36500 days. Native retention asynchronously purges expired unsigned submissions. Signed legal submissions remain exempt. No immediate purge is performed by this configuration call."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or minimal durable receipt.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"updated":{"const":true}},"required":["id","updated"]}},"required":["data"]}}}},"400":{"description":"Invalid configuration, unsupported cursor or request limit exceeded."},"401":{"description":"Missing, expired or invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported approval."},"404":{"description":"Record, live parent or attachment proof unavailable."},"409":{"description":"Idempotency conflict or signed-submission confirmation required."},"413":{"description":"Request or attachment exceeds its byte limit."},"415":{"description":"Unsupported request or attachment MIME type."},"416":{"description":"Attachment Range requests are unsupported."},"429":{"description":"Rate or audit budget exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"retentionDays":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["retentionDays"]}}}}
  /api/v1/forms/{id}/brand-style:
    post:
      x-seedly-oauth-scope: "forms:write"
      x-seedly-standard-scope: "forms:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "applyFormBrandStyle"
      summary: "applyFormBrandStyle"
      tags: ["Forms"]
      description: "New location-wide Standard v2 or OAuth operation approval only. Legacy keys, CloseBot and restricted record grants cannot enter these operations. Stable Idempotency-Key required; retries recheck live authority and parent/source proofs. Applies an existing same-location native brand-style preset. Changes to a published form additionally require publication and active automation authority."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or minimal durable receipt.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"updated":{"const":true}},"required":["id","updated"]}},"required":["data"]}}}},"400":{"description":"Invalid configuration, unsupported cursor or request limit exceeded."},"401":{"description":"Missing, expired or invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported approval."},"404":{"description":"Record, live parent or attachment proof unavailable."},"409":{"description":"Idempotency conflict or signed-submission confirmation required."},"413":{"description":"Request or attachment exceeds its byte limit."},"415":{"description":"Unsupported request or attachment MIME type."},"416":{"description":"Attachment Range requests are unsupported."},"429":{"description":"Rate or audit budget exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"brandStyleId":{"type":"string","description":"brandStyles identifier."}},"required":["brandStyleId"]}}}}
  /api/v1/calendars/{id}/availability-rules:
    get:
      x-seedly-oauth-scope: "calendars:read"
      x-seedly-standard-scope: "calendars:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "listCalendarAvailabilityRules"
      summary: "listCalendarAvailabilityRules"
      tags: ["Calendars"]
      description: "Fresh location-wide Standard v2 or OAuth operation approval only; no legacy keys or restricted grants. Calendar parent must be live and in the same location. Insertion-order cursor pagination."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":8192}}]
      responses: {"200":{"description":"Safe projection or idempotent receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"calendarId":{"type":"string"},"dayOfWeek":{"type":"integer","minimum":0,"maximum":6},"startTime":{"type":"string","pattern":"^(?:[01][0-9]|2[0-3]):[0-5][0-9]$"},"endTime":{"type":"string","pattern":"^(?:(?:[01][0-9]|2[0-3]):[0-5][0-9]|24:00)$"},"isAvailable":{"type":"boolean"}},"required":["id","calendarId","dayOfWeek","startTime","endTime","isAvailable"]}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Invalid input, scheduling overlap, cursor or supported operation size exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported grant."},"404":{"description":"Record or live parent unavailable."},"429":{"description":"Rate limit exceeded."}}
    put:
      x-seedly-oauth-scope: "calendars:write"
      x-seedly-standard-scope: "calendars:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "replaceCalendarAvailabilityRules"
      summary: "replaceCalendarAvailabilityRules"
      tags: ["Calendars"]
      description: "Fresh location-wide Standard v2 or OAuth operation approval only; no legacy keys or restricted grants. Calendar parent must be live and in the same location. Stable Idempotency-Key required, maximum body 256 KiB. Writes use native calendar business rules and a reachable author; responses contain minimal receipts. Replays recheck current authority and parent binding. Replaces all rules; [] clears them. Both incoming and existing rule collections must contain at most 100 rows. Start must precede end. Active rules on the same weekday may touch but cannot overlap. Sunday is 0, Saturday 6."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or idempotent receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"updated":{"const":true}},"required":["id","updated"]}}}}}},"400":{"description":"Invalid input, scheduling overlap, cursor or supported operation size exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported grant."},"404":{"description":"Record or live parent unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Idempotency conflict."},"413":{"description":"Body too large."},"415":{"description":"JSON content type required."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"rules":{"type":"array","maxItems":100,"items":{"type":"object","additionalProperties":false,"properties":{"dayOfWeek":{"type":"integer","minimum":0,"maximum":6},"startTime":{"type":"string","pattern":"^(?:[01][0-9]|2[0-3]):[0-5][0-9]$"},"endTime":{"type":"string","pattern":"^(?:(?:[01][0-9]|2[0-3]):[0-5][0-9]|24:00)$"},"isAvailable":{"type":"boolean"}},"required":["dayOfWeek","startTime","endTime","isAvailable"]}}},"required":["rules"]}}}}
  /api/v1/calendars/{id}/date-overrides:
    get:
      x-seedly-oauth-scope: "calendars:read"
      x-seedly-standard-scope: "calendars:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "listCalendarDateOverrides"
      summary: "listCalendarDateOverrides"
      tags: ["Calendars"]
      description: "Fresh location-wide Standard v2 or OAuth operation approval only; no legacy keys or restricted grants. Calendar parent must be live and in the same location. Insertion-order cursor pagination; nullable optional hours and reason."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":8192}}]
      responses: {"200":{"description":"Safe projection or idempotent receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"calendarId":{"type":"string"},"date":{"type":"string","format":"date"},"isUnavailable":{"type":"boolean"},"startTime":{"type":["string","null"]},"endTime":{"type":["string","null"]},"reason":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}},"required":["id","calendarId","date","isUnavailable","startTime","endTime","reason","createdAt"]}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Invalid input, scheduling overlap, cursor or supported operation size exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported grant."},"404":{"description":"Record or live parent unavailable."},"429":{"description":"Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "calendars:write"
      x-seedly-standard-scope: "calendars:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "createCalendarDateOverride"
      summary: "createCalendarDateOverride"
      tags: ["Calendars"]
      description: "Fresh location-wide Standard v2 or OAuth operation approval only; no legacy keys or restricted grants. Calendar parent must be live and in the same location. Stable Idempotency-Key required, maximum body 256 KiB. Writes use native calendar business rules and a reachable author; responses contain minimal receipts. Replays recheck current authority and parent binding. Date must be a real calendar date. Available overrides require start and end with start before end. Unavailable overrides clear hours. Reason maximum 1000 characters."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or idempotent receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"created":{"const":true}},"required":["id","created"]}}}}}},"400":{"description":"Invalid input, scheduling overlap, cursor or supported operation size exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported grant."},"404":{"description":"Record or live parent unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Idempotency conflict."},"413":{"description":"Body too large."},"415":{"description":"JSON content type required."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"date":{"type":"string","format":"date"},"isUnavailable":{"type":"boolean"},"startTime":{"type":"string","pattern":"^(?:[01][0-9]|2[0-3]):[0-5][0-9]$"},"endTime":{"type":"string","pattern":"^(?:(?:[01][0-9]|2[0-3]):[0-5][0-9]|24:00)$"},"reason":{"type":"string","maxLength":1000}},"required":["date","isUnavailable"]}}}}
  /api/v1/calendar-date-overrides/{id}:
    patch:
      x-seedly-oauth-scope: "calendars:write"
      x-seedly-standard-scope: "calendars:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "updateCalendarDateOverride"
      summary: "updateCalendarDateOverride"
      tags: ["Calendars"]
      description: "Fresh location-wide Standard v2 or OAuth operation approval only; no legacy keys or restricted grants. Calendar parent must be live and in the same location. Stable Idempotency-Key required, maximum body 256 KiB. Writes use native calendar business rules and a reachable author; responses contain minimal receipts. Replays recheck current authority and parent binding. Date and parent calendar are immutable. Validates merged hours; isUnavailable:true clears stored hours. Omitted properties remain unchanged. Null is not accepted."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or idempotent receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"updated":{"const":true}},"required":["id","updated"]}}}}}},"400":{"description":"Invalid input, scheduling overlap, cursor or supported operation size exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported grant."},"404":{"description":"Record or live parent unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Idempotency conflict."},"413":{"description":"Body too large."},"415":{"description":"JSON content type required."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"isUnavailable":{"type":"boolean"},"startTime":{"type":"string","pattern":"^(?:[01][0-9]|2[0-3]):[0-5][0-9]$"},"endTime":{"type":"string","pattern":"^(?:(?:[01][0-9]|2[0-3]):[0-5][0-9]|24:00)$"},"reason":{"type":"string","maxLength":1000}},"required":[],"minProperties":1}}}}
    delete:
      x-seedly-oauth-scope: "calendars:delete"
      x-seedly-standard-scope: "calendars:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "deleteCalendarDateOverride"
      summary: "deleteCalendarDateOverride"
      tags: ["Calendars"]
      description: "Fresh location-wide Standard v2 or OAuth operation approval only; no legacy keys or restricted grants. Calendar parent must be live and in the same location. Stable Idempotency-Key required, maximum body 256 KiB. Writes use native calendar business rules and a reachable author; responses contain minimal receipts. Replays recheck current authority and parent binding. Deletes only the specified override, not its calendar. No request body. Replay retains private parent proof and returns only the deletion receipt."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or idempotent receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"deleted":{"const":true}},"required":["id","deleted"]}}}}}},"400":{"description":"Invalid input, scheduling overlap, cursor or supported operation size exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked, stale or unsupported grant."},"404":{"description":"Record or live parent unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Idempotency conflict."},"413":{"description":"Body too large."},"415":{"description":"JSON content type required."}}
  /api/v1/tags/{id}/merge:
    post:
      x-seedly-oauth-scope: "tags:write"
      x-seedly-standard-scope: "tags:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: mergeIntegrationTag
      summary: "merge Integration Tag"
      tags: [Integrations]
      description: "Explicitly approved location-wide tag operation. Rename requires tags:write; delete requires tags:delete; merge requires both. Every operation additionally requires contacts:write and opportunities:write with access to all location pipelines. Uses native asynchronous contact/opportunity tag rewrites. Idempotency-Key required; no new rewrite can start while another is active. Response acknowledges accepted cleanup, which continues after credential revocation. Legacy keys and restricted grants are denied. Native UI and integration rewrites share the same serialization guard. A busy rejection commits no mutation or receipt; retry after cleanup finishes. New writes and receipt retries recheck current pipeline ACLs. This acknowledges acceptance, not background completion."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Authorized projection or idempotent write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","targetTagId","merged"],"properties":{"id":{"type":"string"},"targetTagId":{"type":"string"},"merged":{"const":true}}}}}}}},"400":{"description":"Invalid request or another tag rewrite is in progress. Wait for cleanup to finish, then retry with the same Idempotency-Key."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked or stale operation approval."},"404":{"description":"Record or parent unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Idempotency key reused for another request."},"413":{"description":"Request body too large."},"415":{"description":"JSON content type required."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["targetTagId"],"properties":{"targetTagId":{"type":"string"}}}}}}
  /api/v1/tags/{id}/rename:
    post:
      x-seedly-oauth-scope: "tags:write"
      x-seedly-standard-scope: "tags:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: renameIntegrationTag
      summary: "rename Integration Tag"
      tags: [Integrations]
      description: "Explicitly approved location-wide tag operation. Rename requires tags:write; delete requires tags:delete; merge requires both. Every operation additionally requires contacts:write and opportunities:write with access to all location pipelines. Uses native asynchronous contact/opportunity tag rewrites. Idempotency-Key required; no new rewrite can start while another is active. Response acknowledges accepted cleanup, which continues after credential revocation. Legacy keys and restricted grants are denied. Native UI and integration rewrites share the same serialization guard. A busy rejection commits no mutation or receipt; retry after cleanup finishes. New writes and receipt retries recheck current pipeline ACLs. This acknowledges acceptance, not background completion."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Authorized projection or idempotent write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"const":true}}}}}}}},"400":{"description":"Invalid request or another tag rewrite is in progress. Wait for cleanup to finish, then retry with the same Idempotency-Key."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked or stale operation approval."},"404":{"description":"Record or parent unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Idempotency key reused for another request."},"413":{"description":"Request body too large."},"415":{"description":"JSON content type required."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":50,"description":"Trimmed nonempty name, without control characters."}}}}}}
  /api/v1/contacts/{id}/activities:
    get:
      x-seedly-oauth-scope: "contacts:read"
      x-seedly-standard-scope: "contacts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listContactActivitySummaries
      summary: "list Contact Activity Summaries"
      tags: [Integrations]
      description: "Location-wide contacts:read. Returns fixed generated category labels only; no raw descriptions, metadata, source records, provider identifiers or private message content. Detailed source content is not part of this feed. Fresh approval required; legacy keys and own/team/selected grants are denied. The contact must exist in the same location and not be deleted. Results use insertion-descending cursor pagination; empty filtered pages can still have a continuation. Timestamps are ISO 8601 strings."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":8192}}]
      responses: {"200":{"description":"Authorized projection or idempotent write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","contactId","type","description","createdAt","summaryOnly"],"properties":{"id":{"type":"string"},"contactId":{"type":"string"},"type":{"type":"string","enum":["contact","note","message","appointment","task","opportunity","campaign","workflow","form","document","invoice","estimate","call","community","other"]},"description":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"summaryOnly":{"const":true}}}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Invalid request."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked or stale operation approval."},"404":{"description":"Record or parent unavailable."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/me/notifications/{id}:
    get:
      x-seedly-oauth-scope: "notifications:read"
      x-seedly-standard-scope: "notifications:read"
      x-seedly-resource-restrictions: {"oauth":["approved_locations","personal_subject"],"standard":["approved_locations","personal_subject"]}
      operationId: getMyNotification
      summary: getMyNotification
      tags: [Integrations]
      description: "Personal authority only, live subject and explicitly selected locations. Location credentials and legacy keys denied. Existing Standard approvals never acquire these operations automatically. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Authorized personal projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["id","type","title","body","isRead","createdAt"],"properties":{"id":{"type":"string"},"type":{"type":"string"},"title":{"type":"string"},"body":{"type":"string"},"createdAt":{"type":"string"},"isRead":{"type":"boolean"}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Unapproved operation or revoked subject/location permission."},"404":{"description":"Notification unavailable."},"409":{"description":"Idempotency request conflict."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
    delete:
      x-seedly-oauth-scope: "notifications:delete"
      x-seedly-standard-scope: "notifications:delete"
      x-seedly-resource-restrictions: {"oauth":["approved_locations","personal_subject"],"standard":["approved_locations","personal_subject"]}
      operationId: deleteMyNotification
      summary: deleteMyNotification
      tags: [Integrations]
      description: "Personal authority only, live subject and explicitly selected locations. Location credentials and legacy keys denied. Existing Standard approvals never acquire these operations automatically. No request body. Removes only the authenticated subject notification, and replay revalidates authority and retained location proof."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Authorized personal projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["id","deleted"],"properties":{"id":{"type":"string"},"deleted":{"const":true}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Unapproved operation or revoked subject/location permission."},"404":{"description":"Notification unavailable."},"409":{"description":"Idempotency request conflict."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
  /api/v1/me/notifications/unread-count:
    get:
      x-seedly-oauth-scope: "notifications:read"
      x-seedly-standard-scope: "notifications:read"
      x-seedly-resource-restrictions: {"oauth":["approved_locations","personal_subject"],"standard":["approved_locations","personal_subject"]}
      operationId: countMyUnreadNotificationPage
      summary: countMyUnreadNotificationPage
      tags: [Integrations]
      description: "Personal authority only, live subject and explicitly selected locations. Location credentials and legacy keys denied. Existing Standard approvals never acquire these operations automatically. Bounded page, default 50/max 100 and 1 MB read budget. count is this page only. Follow cursor while hasMore is true, including zero-count pages; aggregate counts for a total. Concurrent arrivals are not a snapshot. Each continuation write needs a new Idempotency-Key; retry an accepted page with the same key/body to return its original receipt. "
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":8192}}]
      responses: {"200":{"description":"Authorized personal projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["count","hasMore","cursor"],"properties":{"count":{"type":"integer","minimum":0},"hasMore":{"type":"boolean"},"cursor":{"type":["string","null"]}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Unapproved operation or revoked subject/location permission."},"404":{"description":"Notification unavailable."},"409":{"description":"Idempotency request conflict."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
  /api/v1/me/notifications/mark-all-read:
    post:
      x-seedly-oauth-scope: "notifications:write"
      x-seedly-standard-scope: "notifications:write"
      x-seedly-resource-restrictions: {"oauth":["approved_locations","personal_subject"],"standard":["approved_locations","personal_subject"]}
      operationId: markMyNotificationPageRead
      summary: markMyNotificationPageRead
      tags: [Integrations]
      description: "Personal authority only, live subject and explicitly selected locations. Location credentials and legacy keys denied. Existing Standard approvals never acquire these operations automatically. Bounded page, default 50/max 100 and 1 MB read budget. count is this page only. Follow cursor while hasMore is true, including zero-count pages; aggregate counts for a total. Concurrent arrivals are not a snapshot. Each continuation write needs a new Idempotency-Key; retry an accepted page with the same key/body to return its original receipt. "
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Authorized personal projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["count","hasMore","cursor"],"properties":{"count":{"type":"integer","minimum":0},"hasMore":{"type":"boolean"},"cursor":{"type":["string","null"]}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Unapproved operation or revoked subject/location permission."},"404":{"description":"Notification unavailable."},"409":{"description":"Idempotency request conflict."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"limit":{"type":"integer","minimum":1,"maximum":100,"default":50},"cursor":{"type":"string","minLength":1,"maxLength":8192}}}}}}
  /api/v1/me/notifications/clear-read:
    post:
      x-seedly-oauth-scope: "notifications:delete"
      x-seedly-standard-scope: "notifications:delete"
      x-seedly-resource-restrictions: {"oauth":["approved_locations","personal_subject"],"standard":["approved_locations","personal_subject"]}
      operationId: clearMyReadNotificationPage
      summary: clearMyReadNotificationPage
      tags: [Integrations]
      description: "Personal authority only, live subject and explicitly selected locations. Location credentials and legacy keys denied. Existing Standard approvals never acquire these operations automatically. Bounded page, default 50/max 100 and 1 MB read budget. count is this page only. Follow cursor while hasMore is true, including zero-count pages; aggregate counts for a total. Concurrent arrivals are not a snapshot. Each continuation write needs a new Idempotency-Key; retry an accepted page with the same key/body to return its original receipt. "
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Authorized personal projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["count","hasMore","cursor"],"properties":{"count":{"type":"integer","minimum":0},"hasMore":{"type":"boolean"},"cursor":{"type":["string","null"]}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Unapproved operation or revoked subject/location permission."},"404":{"description":"Notification unavailable."},"409":{"description":"Idempotency request conflict."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"limit":{"type":"integer","minimum":1,"maximum":100,"default":50},"cursor":{"type":"string","minLength":1,"maxLength":8192}}}}}}
  /api/v1/me/notification-preferences/{id}:
    get:
      x-seedly-oauth-scope: "notification-preferences:read"
      x-seedly-standard-scope: "notification-preferences:read"
      x-seedly-resource-restrictions: {"oauth":["approved_locations","personal_subject"],"standard":["approved_locations","personal_subject"]}
      operationId: getMyNotificationPreferences
      summary: getMyNotificationPreferences
      tags: [Integrations]
      description: "Personal authority only, live subject and explicitly selected locations. Location credentials and legacy keys denied. Existing Standard approvals never acquire these operations automatically. Location id is the approved internal sub-account id. Native settings view/update permission is checked on the target location membership. Changes configure future native delivery only; no immediate sends, recipient edits or provider access. JSON at most 32768 bytes. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Authorized personal projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"allOf":[{"$ref":"#/components/schemas/PersonalNotificationPreferences"}]}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Unapproved operation or revoked subject/location permission."},"404":{"description":"Notification unavailable."},"409":{"description":"Idempotency request conflict."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
    patch:
      x-seedly-oauth-scope: "notification-preferences:write"
      x-seedly-standard-scope: "notification-preferences:write"
      x-seedly-resource-restrictions: {"oauth":["approved_locations","personal_subject"],"standard":["approved_locations","personal_subject"]}
      operationId: updateMyNotificationPreferences
      summary: updateMyNotificationPreferences
      tags: [Integrations]
      description: "Personal authority only, live subject and explicitly selected locations. Location credentials and legacy keys denied. Existing Standard approvals never acquire these operations automatically. Location id is the approved internal sub-account id. Native settings view/update permission is checked on the target location membership. Changes configure future native delivery only; no immediate sends, recipient edits or provider access. JSON at most 32768 bytes. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Authorized personal projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"const":true}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Unapproved operation or revoked subject/location permission."},"404":{"description":"Notification unavailable."},"409":{"description":"Idempotency request conflict."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonalNotificationPreferenceUpdate"}}}}
  /api/v1/me/notifications/{id}/read:
    patch:
      x-seedly-oauth-scope: "notifications:write"
      x-seedly-standard-scope: "notifications:write"
      x-seedly-resource-restrictions: {"oauth":["approved_locations","personal_subject"],"standard":["approved_locations","personal_subject"]}
      operationId: markMyNotificationRead
      summary: "mark My Notification Read"
      tags: [Integrations]
      description: "Dedicated OAuth authority grants or explicitly approved authority API keys only. Location tokens, legacy and Standard location keys cannot use this endpoint. Authority version 1 fixes the agency, subject and explicit selected locations at approval; headers cannot override them. Live membership, role, app policy and revocation are checked on every call. Marks only the consenting user notification read. Send an empty JSON object, at most 1024 bytes, with Idempotency-Key."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Authorized projection or idempotent write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"const":true}}}}}}}},"400":{"description":"Invalid request."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked or stale operation approval."},"404":{"description":"Record or parent unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Idempotency key reused for another request."},"413":{"description":"Request body too large."},"415":{"description":"JSON content type required."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}
  /api/v1/me/notifications:
    get:
      x-seedly-oauth-scope: "notifications:read"
      x-seedly-standard-scope: "notifications:read"
      x-seedly-resource-restrictions: {"oauth":["approved_locations","personal_subject"],"standard":["approved_locations","personal_subject"]}
      operationId: listMyNotifications
      summary: "list My Notifications"
      tags: [Integrations]
      description: "Dedicated OAuth authority grants or explicitly approved authority API keys only. Location tokens, legacy and Standard location keys cannot use this endpoint. Authority version 1 fixes the agency, subject and explicit selected locations at approval; headers cannot override them. Live membership, role, app policy and revocation are checked on every call. Personal subject only. Native location and private-message visibility rules apply."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":8192}}]
      responses: {"200":{"description":"Authorized projection or idempotent write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","type","title","body","isRead","createdAt"],"properties":{"id":{"type":"string"},"type":{"type":"string"},"title":{"type":"string"},"body":{"type":"string"},"isRead":{"type":"boolean"},"createdAt":{"type":"string"}}}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Invalid request."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked or stale operation approval."},"404":{"description":"Record or parent unavailable."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/agency/locations:
    get:
      x-seedly-oauth-scope: "agency-locations:read"
      x-seedly-standard-scope: "agency-locations:read"
      x-seedly-resource-restrictions: {"oauth":["approved_locations"],"standard":["approved_locations"]}
      operationId: listAuthorizedAgencyLocations
      summary: "list Authorized Agency Locations"
      tags: [Integrations]
      description: "Dedicated OAuth authority grants or explicitly approved authority API keys only. Location tokens, legacy and Standard location keys cannot use this endpoint. Authority version 1 fixes the agency, subject and explicit selected locations at approval; headers cannot override them. Live membership, role, app policy and revocation are checked on every call. Returns only the selected locations, at most 100. Future locations are never added automatically."
      parameters: []
      responses: {"200":{"description":"Authorized projection or idempotent write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","locationId","name"],"properties":{"id":{"type":"string"},"locationId":{"type":["string","null"]},"name":{"type":"string"}}}}}}}}},"400":{"description":"Invalid request."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked or stale operation approval."},"404":{"description":"Record or parent unavailable."},"429":{"description":"Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "agency-locations:admin"
      x-seedly-standard-scope: "agency-locations:admin"
      x-seedly-resource-restrictions: {"oauth":["approved_locations"],"standard":["approved_locations"]}
      operationId: postAgencyLocations
      tags: [Agency]
      summary: Provision a location
      description: "Agency authority only. Selected locations are fixed at approval and live role permissions apply. Location credentials and legacy keys are denied. Returns a receipt only. The new location does not join this approval."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string"},"slug":{"type":"string"}}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/agency:
    get:
      x-seedly-oauth-scope: "agency:read"
      x-seedly-standard-scope: "agency:read"
      x-seedly-resource-restrictions: {"oauth":["approved_locations"],"standard":["approved_locations"]}
      operationId: getAuthorizedAgency
      summary: "get Authorized Agency"
      tags: [Integrations]
      description: "Dedicated OAuth authority grants or explicitly approved authority API keys only. Location tokens, legacy and Standard location keys cannot use this endpoint. Authority version 1 fixes the agency, subject and explicit selected locations at approval; headers cannot override them. Live membership, role, app policy and revocation are checked on every call."
      parameters: []
      responses: {"200":{"description":"Authorized projection or idempotent write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"}}}}}}}},"400":{"description":"Invalid request."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked or stale operation approval."},"404":{"description":"Record or parent unavailable."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/calendars/{id}:
    delete:
      x-seedly-oauth-scope: "calendars:delete"
      x-seedly-standard-scope: "calendars:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "calendarDelete"
      summary: "DELETE /api/v1/calendars/{id}"
      tags: ["Integrations"]
      description: "Location-wide reviewed Standard v2 or OAuth operation. No legacy API key, CloseBot or restricted record grant access. Dependency-free deletion only. Returns 409 when the calendar has appointments, active slot holds, booking links, booking submissions, services, external sync or an open cascade deletion. Requires a stable Idempotency-Key."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Safe projection or durable receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","deleted"],"properties":{"id":{"type":"string"},"deleted":{"type":"boolean"}}}}}}}},"400":{"description":"Invalid input."},"401":{"description":"Invalid credential."},"403":{"description":"Operation or reference not approved."},"404":{"description":"Record or parent unavailable."},"409":{"description":"Conflict with current state or an earlier idempotency request."},"413":{"description":"Body too large."},"415":{"description":"JSON required."},"429":{"description":"Rate limited."}}
    get:
      x-seedly-oauth-scope: "calendars:read"
      x-seedly-standard-scope: "calendars:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getIntegrationCalendar
      summary: "get Integration Calendar"
      tags: [Integrations]
      description: "Location-wide calendar profile. Requires fresh calendars:read operation approval."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Authorized projection or idempotent write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","name","description","slug","timezone","type","isActive","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"slug":{"type":"string"},"timezone":{"type":"string"},"type":{"type":"string"},"isActive":{"type":"boolean"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}}}}}}},"400":{"description":"Invalid request."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked or stale operation approval."},"404":{"description":"Record or parent unavailable."},"429":{"description":"Rate limit exceeded."}}
    patch:
      x-seedly-oauth-scope: "calendars:write"
      x-seedly-standard-scope: "calendars:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateIntegrationCalendar
      summary: "update Integration Calendar"
      tags: [Integrations]
      description: "Update calendar profile using native calendar business rules. Requires calendars:write and calendar plan feature. Stable Idempotency-Key required. Maximum body 256 KiB."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Authorized projection or idempotent write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"const":true}}}}}}}},"400":{"description":"Invalid request."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked or stale operation approval."},"404":{"description":"Record or parent unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Idempotency key reused for another request."},"413":{"description":"Request body too large."},"415":{"description":"JSON content type required."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":255},"slug":{"type":"string","minLength":1,"maxLength":100},"timezone":{"type":"string","maxLength":100},"description":{"type":"string","maxLength":5000},"isActive":{"type":"boolean"}},"minProperties":1}}}}
  /api/v1/workflow-executions/{id}/logs:
    get:
      x-seedly-oauth-scope: "workflows:read"
      x-seedly-standard-scope: "workflows:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listWorkflowExecutionLogs
      summary: "list Workflow Execution Logs"
      tags: [Integrations]
      description: "Location-wide Standard v2 or OAuth with fresh workflows:read approval. Executions and logs additionally require contacts:read. Safe summaries only; definitions, raw execution context, node inputs, outputs, errors and provider secrets are omitted. Missing or deleted parent resources are unavailable."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":8192}}]
      responses: {"200":{"description":"Authorized projection or idempotent write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","executionId","nodeId","nodeType","status","durationMs","createdAt"],"properties":{"id":{"type":"string"},"executionId":{"type":"string"},"nodeId":{"type":"string"},"nodeType":{"type":"string"},"status":{"type":"string"},"durationMs":{"type":["number","null"]},"createdAt":{"type":"string"}}}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Invalid request."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked or stale operation approval."},"404":{"description":"Record or parent unavailable."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/workflow-executions/{id}:
    get:
      x-seedly-oauth-scope: "workflows:read"
      x-seedly-standard-scope: "workflows:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getWorkflowExecution
      summary: "get Workflow Execution"
      tags: [Integrations]
      description: "Location-wide Standard v2 or OAuth with fresh workflows:read approval. Executions and logs additionally require contacts:read. Safe summaries only; definitions, raw execution context, node inputs, outputs, errors and provider secrets are omitted. Missing or deleted parent resources are unavailable."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Authorized projection or idempotent write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","workflowId","contactId","status","isTest","isDryRun","currentNodeId","publishedVersion","startedAt","completedAt"],"properties":{"id":{"type":"string"},"workflowId":{"type":"string"},"contactId":{"type":["string","null"]},"status":{"type":"string"},"isTest":{"type":"boolean"},"isDryRun":{"type":"boolean"},"currentNodeId":{"type":["string","null"]},"publishedVersion":{"type":["number","null"]},"startedAt":{"type":"string"},"completedAt":{"type":["string","null"]}}}}}}}},"400":{"description":"Invalid request."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked or stale operation approval."},"404":{"description":"Record or parent unavailable."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/workflows/{id}/executions:
    get:
      x-seedly-oauth-scope: "workflows:read"
      x-seedly-standard-scope: "workflows:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listWorkflowExecutions
      summary: "list Workflow Executions"
      tags: [Integrations]
      description: "Location-wide Standard v2 or OAuth with fresh workflows:read approval. Executions and logs additionally require contacts:read. Safe summaries only; definitions, raw execution context, node inputs, outputs, errors and provider secrets are omitted. Missing or deleted parent resources are unavailable."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":8192}}]
      responses: {"200":{"description":"Authorized projection or idempotent write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","workflowId","contactId","status","isTest","isDryRun","currentNodeId","publishedVersion","startedAt","completedAt"],"properties":{"id":{"type":"string"},"workflowId":{"type":"string"},"contactId":{"type":["string","null"]},"status":{"type":"string"},"isTest":{"type":"boolean"},"isDryRun":{"type":"boolean"},"currentNodeId":{"type":["string","null"]},"publishedVersion":{"type":["number","null"]},"startedAt":{"type":"string"},"completedAt":{"type":["string","null"]}}}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Invalid request."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked or stale operation approval."},"404":{"description":"Record or parent unavailable."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/workflows/{id}:
    delete:
      x-seedly-oauth-scope: "workflows:delete"
      x-seedly-standard-scope: "workflows:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteWorkflow
      tags: [Workflows]
      summary: "Delete a workflow"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Removes the workflow, its versions, its run history and logs, in the background. Cannot be undone. An active or paused workflow also requires workflows:publish, and a workflow with runs in progress also requires workflows:unenroll, because deleting stops them. A workflow whose versions and samples are too large to delete in one call is refused with 409. Refused for test credentials. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.
    get:
      x-seedly-oauth-scope: "workflows:read"
      x-seedly-standard-scope: "workflows:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getWorkflow
      summary: "get Workflow"
      tags: [Integrations]
      description: "Location-wide Standard v2 or OAuth with fresh workflows:read approval. Executions and logs additionally require contacts:read. Safe summaries only; definitions, raw execution context, node inputs, outputs, errors and provider secrets are omitted. Missing or deleted parent resources are unavailable."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Authorized projection or idempotent write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","name","description","status","triggerType","publishedVersion","publishedAt","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string"},"triggerType":{"type":["string","null"]},"publishedVersion":{"type":["number","null"]},"publishedAt":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}}}}}}},"400":{"description":"Invalid request."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked or stale operation approval."},"404":{"description":"Record or parent unavailable."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/workflows:
    post:
      x-seedly-oauth-scope: "workflows:write"
      x-seedly-standard-scope: "workflows:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createWorkflow
      tags: [Workflows]
      summary: "Create a workflow draft"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Requires workflows:write. The draft does not run until published. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string"},"description":{"type":"string"},"dag":{"type":"object"},"triggerType":{"type":"string"},"triggerConfig":{"type":"object"},"allowReEntry":{"type":"boolean"},"stopOnResponse":{"type":"boolean"}},"required":["name"]}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.
    get:
      x-seedly-oauth-scope: "workflows:read"
      x-seedly-standard-scope: "workflows:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listWorkflows
      summary: "list Workflows"
      tags: [Integrations]
      description: "Location-wide Standard v2 or OAuth with fresh workflows:read approval. Executions and logs additionally require contacts:read. Safe summaries only; definitions, raw execution context, node inputs, outputs, errors and provider secrets are omitted. Missing or deleted parent resources are unavailable."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":8192}}]
      responses: {"200":{"description":"Authorized projection or idempotent write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","name","description","status","triggerType","publishedVersion","publishedAt","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string"},"triggerType":{"type":["string","null"]},"publishedVersion":{"type":["number","null"]},"publishedAt":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Invalid request."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked or stale operation approval."},"404":{"description":"Record or parent unavailable."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/companies/{id}/notes:
    get:
      x-seedly-oauth-scope: "companies:read"
      x-seedly-standard-scope: "companies:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "listCompanyNotes"
      tags: ["Companies"]
      summary: "listCompanyNotes"
      description: "Location-wide Standard v2 or OAuth with fresh operation approval only; legacy keys and own/team/selected grants are denied. Reads require both companies:read and contacts:read. Writes require companies:write and its all-record native permissions. Notes expose no author/tenant metadata, mentions or attachments. Writes accept content up to 50,000 characters and isPinned; unknown fields are rejected. Writes return a minimal ID/created or ID/updated receipt. Replays recheck current authority and parent existence; changed request details conflict. No contact-note workflow is triggered. Pagination follows descending insertion order, not pinned-first order; pin edits do not reorder the list."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":8192}}]
      responses: {"200":{"description":"Authorized projection or minimal write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/IntegrationCompanyNote"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Invalid request or cursor."},"401":{"description":"Invalid credential."},"403":{"description":"Missing or stale approval, unsupported record grant or insufficient live permission."},"404":{"description":"Resource or parent unavailable."},"429":{"description":"Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "companies:write"
      x-seedly-standard-scope: "companies:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "createCompanyNote"
      tags: ["Companies"]
      summary: "createCompanyNote"
      description: "Location-wide Standard v2 or OAuth with fresh operation approval only; legacy keys and own/team/selected grants are denied. Reads require both companies:read and contacts:read. Writes require companies:write and its all-record native permissions. Notes expose no author/tenant metadata, mentions or attachments. Writes accept content up to 50,000 characters and isPinned; unknown fields are rejected. Writes return a minimal ID/created or ID/updated receipt. Replays recheck current authority and parent existence; changed request details conflict. No contact-note workflow is triggered."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Authorized projection or minimal write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/IntegrationValueWriteReceipt"}}}}}},"400":{"description":"Invalid request or cursor."},"401":{"description":"Invalid credential."},"403":{"description":"Missing or stale approval, unsupported record grant or insufficient live permission."},"404":{"description":"Resource or parent unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Idempotency key reused with different request details."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"content":{"type":"string","maxLength":50000},"isPinned":{"type":"boolean"}},"required":["content"]}}}}
  /api/v1/company-notes/{id}:
    get:
      x-seedly-oauth-scope: "companies:read"
      x-seedly-standard-scope: "companies:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getCompanyNote"
      tags: ["Companies"]
      summary: "getCompanyNote"
      description: "Location-wide Standard v2 or OAuth with fresh operation approval only; legacy keys and own/team/selected grants are denied. Reads require both companies:read and contacts:read. Writes require companies:write and its all-record native permissions. Notes expose no author/tenant metadata, mentions or attachments. Writes accept content up to 50,000 characters and isPinned; unknown fields are rejected. Writes return a minimal ID/created or ID/updated receipt. Replays recheck current authority and parent existence; changed request details conflict. No contact-note workflow is triggered."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Authorized projection or minimal write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/IntegrationCompanyNote"}}}}}},"400":{"description":"Invalid request or cursor."},"401":{"description":"Invalid credential."},"403":{"description":"Missing or stale approval, unsupported record grant or insufficient live permission."},"404":{"description":"Resource or parent unavailable."},"429":{"description":"Rate limit exceeded."}}
    patch:
      x-seedly-oauth-scope: "companies:write"
      x-seedly-standard-scope: "companies:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "updateCompanyNote"
      tags: ["Companies"]
      summary: "updateCompanyNote"
      description: "Location-wide Standard v2 or OAuth with fresh operation approval only; legacy keys and own/team/selected grants are denied. Reads require both companies:read and contacts:read. Writes require companies:write and its all-record native permissions. Notes expose no author/tenant metadata, mentions or attachments. Writes accept content up to 50,000 characters and isPinned; unknown fields are rejected. Writes return a minimal ID/created or ID/updated receipt. Replays recheck current authority and parent existence; changed request details conflict. No contact-note workflow is triggered."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Authorized projection or minimal write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/IntegrationValueWriteReceipt"}}}}}},"400":{"description":"Invalid request or cursor."},"401":{"description":"Invalid credential."},"403":{"description":"Missing or stale approval, unsupported record grant or insufficient live permission."},"404":{"description":"Resource or parent unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Idempotency key reused with different request details."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"content":{"type":"string","maxLength":50000},"isPinned":{"type":"boolean"}},"minProperties":1}}}}
    delete:
      x-seedly-oauth-scope: "companies:delete"
      x-seedly-standard-scope: "companies:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteCompanyNote
      summary: "delete Company Note"
      tags: [Integrations]
      description: "Requires fresh Standard v2 or OAuth operation approval and Idempotency-Key. No request body. Replays recheck authority and live parent. Contact-note deletion supports at most 100 attachment references and deletes only storage owned by the location."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Authorized projection or idempotent write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","deleted"],"properties":{"id":{"type":"string"},"deleted":{"const":true}}}}}}}},"400":{"description":"Invalid request."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked or stale operation approval."},"404":{"description":"Record or parent unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Idempotency key reused for another request."},"413":{"description":"Request body too large."},"415":{"description":"JSON content type required."}}
  /api/v1/members:
    get:
      x-seedly-oauth-scope: "members:read"
      x-seedly-standard-scope: "members:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getMembers
      tags: [Directory]
      summary: List location members
      description: "Standard v2 or OAuth only; legacy keys are denied. Existing Standard keys need explicit approval of this route. Record-restricted grants are denied."
      parameters: [{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/member-invitations:
    get:
      x-seedly-oauth-scope: "members:read"
      x-seedly-standard-scope: "members:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getMemberInvitations
      tags: [Directory]
      summary: List pending invitations
      description: "Standard v2 or OAuth only; legacy keys are denied. Existing Standard keys need explicit approval of this route. Record-restricted grants are denied."
      parameters: [{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "members:admin"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: postMemberInvitations
      tags: [Directory]
      summary: Invite a member
      description: "Acts through the live role of the consenting person. Native rank, permission ceiling and containment checks apply, so an app can never grant more than that person holds, and cannot change that person's own access. Not available to Standard location keys, which have no human authority to prove. Location memberships and location roles only. Always creates a pending invitation and returns the same response whether or not the address has an account. The invited person accepts it in the application."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"email":{"type":"string"},"roleId":{"type":"string"}}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/team-rosters/{id}:
    get:
      x-seedly-oauth-scope: "members:read"
      x-seedly-standard-scope: "members:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getTeamRostersById
      tags: [Directory]
      summary: Read a team roster
      description: "Standard v2 or OAuth only; legacy keys are denied. Existing Standard keys need explicit approval of this route. Record-restricted grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
    put:
      x-seedly-oauth-scope: "teams:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: putTeamRostersById
      tags: [Directory]
      summary: Replace a team roster
      description: "Acts through the live role of the consenting person. Native rank, permission ceiling and containment checks apply, so an app can never grant more than that person holds, and cannot change that person's own access. Not available to Standard location keys, which have no human authority to prove. Location memberships and location roles only."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"userIds":{"type":"array"}}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/member-invitations/{id}/revoke:
    post:
      x-seedly-oauth-scope: "members:admin"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: postMemberInvitationsByIdRevoke
      tags: [Directory]
      summary: Revoke an invitation
      description: "Acts through the live role of the consenting person. Native rank, permission ceiling and containment checks apply, so an app can never grant more than that person holds, and cannot change that person's own access. Not available to Standard location keys, which have no human authority to prove. Location memberships and location roles only."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/member-invitations/{id}/resend:
    post:
      x-seedly-oauth-scope: "members:admin"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: postMemberInvitationsByIdResend
      tags: [Directory]
      summary: Resend an invitation
      description: "Acts through the live role of the consenting person. Native rank, permission ceiling and containment checks apply, so an app can never grant more than that person holds, and cannot change that person's own access. Not available to Standard location keys, which have no human authority to prove. Location memberships and location roles only."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/members/{id}/role:
    put:
      x-seedly-oauth-scope: "members:admin"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: putMembersByIdRole
      tags: [Directory]
      summary: Change a member role
      description: "Acts through the live role of the consenting person. Native rank, permission ceiling and containment checks apply, so an app can never grant more than that person holds, and cannot change that person's own access. Not available to Standard location keys, which have no human authority to prove. Location memberships and location roles only."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"roleId":{"type":"string"}}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/members/{id}/active:
    put:
      x-seedly-oauth-scope: "members:admin"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: putMembersByIdActive
      tags: [Directory]
      summary: Activate or deactivate a member
      description: "Acts through the live role of the consenting person. Native rank, permission ceiling and containment checks apply, so an app can never grant more than that person holds, and cannot change that person's own access. Not available to Standard location keys, which have no human authority to prove. Location memberships and location roles only."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"isActive":{"type":"boolean"}}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/members/{id}/profile:
    put:
      x-seedly-oauth-scope: "members:admin"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: putMemberProfile
      tags: [Directory]
      summary: Change a member profile
      description: "OAuth only, as the consenting person, who must outrank the member. Accepts jobTitle, bio, timezone and calendarColor. Phone is not accepted. You cannot change your own membership."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object"}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/members/{id}/copy-role:
    put:
      x-seedly-oauth-scope: "members:admin"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: putMemberCopyRole
      tags: [Directory]
      summary: Copy a role from another member
      description: "OAuth only. sourceMemberId must be an active member of this location. The same rank, ceiling and module limits as a role change apply."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object"}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/members/{id}/team-membership:
    put:
      x-seedly-oauth-scope: "teams:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: putMemberTeamMembership
      tags: [Directory]
      summary: Add or remove a member on a team
      description: "OAuth only. Teams of this location only. A team the consenting person belongs to cannot be changed."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object"}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/members/{id}/remove:
    post:
      x-seedly-oauth-scope: "members:admin"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: postMembersByIdRemove
      tags: [Directory]
      summary: Remove a member
      description: "Acts through the live role of the consenting person. Native rank, permission ceiling and containment checks apply, so an app can never grant more than that person holds, and cannot change that person's own access. Not available to Standard location keys, which have no human authority to prove. Location memberships and location roles only."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/roles:
    get:
      x-seedly-oauth-scope: "roles:read"
      x-seedly-standard-scope: "roles:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getRoles
      tags: [Directory]
      summary: List roles
      description: "Standard v2 or OAuth only; legacy keys are denied. Existing Standard keys need explicit approval of this route. Record-restricted grants are denied."
      parameters: [{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "roles:admin"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: postRoles
      tags: [Directory]
      summary: Create a location role
      description: "Acts through the live role of the consenting person. Native rank, permission ceiling and containment checks apply, so an app can never grant more than that person holds, and cannot change that person's own access. Not available to Standard location keys, which have no human authority to prove. Location memberships and location roles only."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string"},"description":{"type":"string"},"permissions":{"type":"array"}}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/roles/{id}:
    get:
      x-seedly-oauth-scope: "roles:read"
      x-seedly-standard-scope: "roles:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getRolesById
      tags: [Directory]
      summary: Read a role
      description: "Standard v2 or OAuth only; legacy keys are denied. Existing Standard keys need explicit approval of this route. Record-restricted grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "roles:admin"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: patchRolesById
      tags: [Directory]
      summary: Update a location role
      description: "Acts through the live role of the consenting person. Native rank, permission ceiling and containment checks apply, so an app can never grant more than that person holds, and cannot change that person's own access. Not available to Standard location keys, which have no human authority to prove. Location memberships and location roles only."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string"},"description":{"type":"string"},"permissions":{"type":"array"}}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/roles/{id}/delete:
    post:
      x-seedly-oauth-scope: "roles:admin"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: postRolesByIdDelete
      tags: [Directory]
      summary: Delete a location role
      description: "Acts through the live role of the consenting person. Native rank, permission ceiling and containment checks apply, so an app can never grant more than that person holds, and cannot change that person's own access. Not available to Standard location keys, which have no human authority to prove. Location memberships and location roles only."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/roles/{id}/duplicate:
    post:
      x-seedly-oauth-scope: "roles:admin"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: postRoleDuplicate
      tags: [Directory]
      summary: Copy a role
      description: "OAuth only. Roles of this location only. The copy stays in this location, and a role beyond your own reach or holding a closed module cannot be copied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object"}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/settings/business:
    get:
      x-seedly-oauth-scope: "settings:read"
      x-seedly-standard-scope: "settings:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getSettingsBusiness
      tags: [Settings]
      summary: Read business settings
      description: "Standard v2 or OAuth only; legacy keys are denied. Existing Standard keys need explicit approval of this route. Record-restricted grants are denied."
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "settings:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: patchSettingsBusiness
      tags: [Settings]
      summary: Update business settings
      description: "Acts through the live role of the consenting person, because the native change is audited as a person. Not available to Standard location keys."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"businessEmail":{"type":"string"},"businessPhone":{"type":"string"},"businessWebsite":{"type":"string"},"legalBusinessName":{"type":"string"},"industry":{"type":"string"},"timezone":{"type":"string"},"dateFormat":{"type":"string"},"language":{"type":"string"},"privacyPolicyUrl":{"type":"string"},"termsUrl":{"type":"string"}}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/settings/reputation:
    get:
      x-seedly-oauth-scope: "settings:read"
      x-seedly-standard-scope: "settings:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getSettingsReputation
      tags: [Settings]
      summary: Read reputation settings
      description: "Standard v2 or OAuth only; legacy keys are denied. Existing Standard keys need explicit approval of this route. Record-restricted grants are denied."
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/settings/domains:
    get:
      x-seedly-oauth-scope: "settings:read"
      x-seedly-standard-scope: "settings:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getSettingsDomains
      tags: [Settings]
      summary: Read domain verification state
      description: "Standard v2 or OAuth only; legacy keys are denied. Existing Standard keys need explicit approval of this route. Record-restricted grants are denied. Returns at most 20 rows in emailDomains; data.truncated is true when more exist."
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/settings/calls:
    get:
      x-seedly-oauth-scope: "settings:read"
      x-seedly-standard-scope: "settings:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getSettingsCalls
      tags: [Settings]
      summary: Call settings
      description: "Allowlisted call configuration. Inbound ring targets also need users:read."
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "settings:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: patchSettingsCalls
      tags: [Settings]
      summary: Change call settings
      description: "OAuth only. Accepts requireDisposition, inboundRingSeconds and outboundRingSeconds. Ring times are 5 to 300 seconds."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object"}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/settings/call-grading:
    get:
      x-seedly-oauth-scope: "settings:read"
      x-seedly-standard-scope: "settings:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getSettingsCallGrading
      tags: [Settings]
      summary: Call grading settings
      description: "Grading rubric, model and thresholds with native defaults."
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/settings/lsa-lead-assistant:
    get:
      x-seedly-oauth-scope: "settings:read"
      x-seedly-standard-scope: "settings:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getSettingsLsaLeadAssistant
      tags: [Settings]
      summary: Local Services lead assistant settings
      description: "Recipient ids also need users:read."
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/settings/send-caps:
    get:
      x-seedly-oauth-scope: "settings:read"
      x-seedly-standard-scope: "settings:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getSettingsSendCaps
      tags: [Settings]
      summary: Send caps
      description: "Effective caps and stored overrides."
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/settings/deal-card:
    get:
      x-seedly-oauth-scope: "settings:read"
      x-seedly-standard-scope: "settings:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getSettingsDealCard
      tags: [Settings]
      summary: Opportunity card settings
      description: "Layout and card zones with native defaults."
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "settings:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: patchSettingsDealCard
      tags: [Settings]
      summary: Change opportunity card settings
      description: "OAuth only. Native field vocabulary applies."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object"}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/settings/invoice-layout:
    get:
      x-seedly-oauth-scope: "settings:read"
      x-seedly-standard-scope: "settings:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getSettingsInvoiceLayout
      tags: [Settings]
      summary: Invoice layout
      description: "Invoice appearance and customer text with native defaults."
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "settings:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: patchSettingsInvoiceLayout
      tags: [Settings]
      summary: Change invoice appearance
      description: "OAuth only. Payment instructions and footer text cannot be changed here."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object"}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/settings/notification-defaults:
    get:
      x-seedly-oauth-scope: "settings:read"
      x-seedly-standard-scope: "settings:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getSettingsNotificationDefaults
      tags: [Settings]
      summary: Notification defaults
      description: "Location defaults for staff notifications."
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "settings:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: patchSettingsNotificationDefaults
      tags: [Settings]
      summary: Change notification defaults
      description: "OAuth only. Supplied events are merged over stored defaults."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object"}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/settings/team-notification-defaults/{id}:
    get:
      x-seedly-oauth-scope: "settings:read"
      x-seedly-standard-scope: "settings:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getSettingsTeamNotificationDefaults
      tags: [Settings]
      summary: Team notification defaults
      description: "Teams of this location only."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "settings:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: patchSettingsTeamNotificationDefaults
      tags: [Settings]
      summary: Change team notification defaults
      description: "OAuth only. Teams of this location only."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object"}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/settings/lifecycle-automation:
    get:
      x-seedly-oauth-scope: "settings:read"
      x-seedly-standard-scope: "settings:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getSettingsLifecycleAutomation
      tags: [Settings]
      summary: Lifecycle automation
      description: "Whether automatic stage changes run, with their rules and active preset."
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "settings:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: patchSettingsLifecycleAutomation
      tags: [Settings]
      summary: Change lifecycle automation
      description: "OAuth only. Supply enabled or presetId. Turning automation on or applying a preset also needs workflows:publish, because stage changes can start published workflows."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object"}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/connections:
    get:
      x-seedly-oauth-scope: "connections:read"
      x-seedly-standard-scope: "connections:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getConnections
      tags: [Settings]
      summary: Read connection state
      description: "Standard v2 or OAuth only; legacy keys are denied. Existing Standard keys need explicit approval of this route. Record-restricted grants are denied. Returns at most 20 rows in googleBusiness or meta; data.truncated is true when more exist."
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-imports/{id}:
    get:
      x-seedly-oauth-scope: "imports:read"
      x-seedly-standard-scope: "imports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getContactImportsById
      tags: [Imports]
      summary: Read a contact import
      description: "Standard v2 or OAuth only; legacy keys are denied. Existing Standard keys need explicit approval of this route. Record-restricted grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-imports:
    post:
      x-seedly-oauth-scope: "imports:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: postContactImports
      tags: [Imports]
      summary: Start a contact import
      description: "Asynchronous CSV contact import owned by the consenting person. Each batch re-proves the original grant and token ceiling. Cancelling stops before the next batch; committed rows stay. Also requires contacts:read approval."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"csvData":{"type":"string"},"duplicateHandling":{"type":"string"},"fieldMapping":{"type":"object"},"importTag":{"type":"string"}}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-imports/{id}/cancel:
    post:
      x-seedly-oauth-scope: "imports:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: postContactImportsByIdCancel
      tags: [Imports]
      summary: Cancel a contact import
      description: "Asynchronous CSV contact import owned by the consenting person. Each batch re-proves the original grant and token ceiling. Cancelling stops before the next batch; committed rows stay. Also requires contacts:read approval."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/agency/locations/{id}:
    get:
      x-seedly-oauth-scope: "agency-location-profiles:read"
      x-seedly-standard-scope: "agency-location-profiles:read"
      x-seedly-resource-restrictions: {"oauth":["approved_locations"],"standard":["approved_locations"]}
      operationId: getAgencyLocationsById
      tags: [Agency]
      summary: Read an approved location
      description: "Agency authority only. Selected locations are fixed at approval and live role permissions apply. Location credentials and legacy keys are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "agency-location-profiles:write"
      x-seedly-resource-restrictions: {"oauth":["approved_locations"]}
      operationId: patchAgencyLocation
      tags: [Agency]
      summary: Rename an approved location
      description: "Agency OAuth only. Accepts name and slug. Location settings cannot be changed here. Location credentials and API keys are refused."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object"}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/agency/settings:
    patch:
      x-seedly-oauth-scope: "agency-settings:write"
      x-seedly-resource-restrictions: {"oauth":["approved_locations","all_active_locations_approved"]}
      operationId: patchAgencySettings
      tags: [Agency]
      summary: Change agency settings
      description: "Agency OAuth only, as an agency-level person with an unrestricted row. Refused unless the approval covers every active location of the agency. Accepts name, logoUrl and liteMode."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object"}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/agency/locations/{id}/suspend:
    post:
      x-seedly-oauth-scope: "agency-locations:admin"
      x-seedly-standard-scope: "agency-locations:admin"
      x-seedly-resource-restrictions: {"oauth":["approved_locations"],"standard":["approved_locations"]}
      operationId: postAgencyLocationsByIdSuspend
      tags: [Agency]
      summary: Suspend an approved location
      description: "Agency authority only. Selected locations are fixed at approval and live role permissions apply. Location credentials and legacy keys are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/agency/locations/{id}/resume:
    post:
      x-seedly-oauth-scope: "agency-locations:admin"
      x-seedly-standard-scope: "agency-locations:admin"
      x-seedly-resource-restrictions: {"oauth":["approved_locations"],"standard":["approved_locations"]}
      operationId: postAgencyLocationsByIdResume
      tags: [Agency]
      summary: Resume an approved location
      description: "Agency authority only. Selected locations are fixed at approval and live role permissions apply. Location credentials and legacy keys are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/agency/locations/{id}/usage:
    get:
      x-seedly-oauth-scope: "agency-usage:read"
      x-seedly-resource-restrictions: {"oauth":["approved_locations"]}
      operationId: getAgencyLocationsByIdUsage
      tags: [Agency]
      summary: Read a location's usage summary for this month
      description: "Agency OAuth only. Selected locations are fixed at approval and live role permissions apply. Returns quantities and billed cents by category. Never returns Stripe, tax or payment method data. Billing writes stay with signed-in staff."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Bounded usage summary.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["id","period","categories","totalBilledCents","partial"],"properties":{"id":{"type":"string"},"period":{"type":"object","required":["start","end"],"properties":{"start":{"type":"string"},"end":{"type":"string"}}},"categories":{"type":"array","maxItems":5,"items":{"type":"object","required":["category","quantity","billedCents"],"properties":{"category":{"type":"string"},"quantity":{"type":"number"},"billedCents":{"type":"number"}}}},"totalBilledCents":{"type":"number"},"partial":{"type":"boolean","description":"True when today's figures may read low until the nightly rollup."}}},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Invalid credential.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '429':
          description: Rate limit exceeded.
  /api/v1/agency/locations/{id}/billing:
    get:
      x-seedly-oauth-scope: "agency-billing:read"
      x-seedly-standard-scope: "agency-billing:read"
      x-seedly-resource-restrictions: {"oauth":["approved_locations"],"standard":["approved_locations"]}
      operationId: getAgencyLocationsByIdBilling
      tags: [Agency]
      summary: Read location account billing state
      description: "Agency authority only. Selected locations are fixed at approval and live role permissions apply. Location credentials and legacy keys are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/users:
    get:
      x-seedly-oauth-scope: "users:read"
      x-seedly-standard-scope: "users:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "listDirectoryUsers"
      tags: ["Directory"]
      summary: "listDirectoryUsers"
      description: "Location-wide Standard v2 or OAuth with fresh approval only; legacy keys and own/team/selected grants are denied. This is safe directory metadata, not agency or personal authority. No emails, phone numbers, role/permission details, credentials or team rosters are returned. Requires users:read and live users:view permission for all records. Lists active users with location access; display names never fall back to email. meta.omitted counts membership rows on this page that reach this location for a person who could not be read because they hold too many memberships; that person is not in data."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":8192}}]
      responses: {"200":{"description":"Authorized projection or minimal write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/IntegrationDirectoryUser"}},"meta":{"allOf":[{"$ref":"#/components/schemas/ProfileReadPage"},{"type":"object","required":["omitted"],"properties":{"omitted":{"type":"integer","minimum":0}}}]}}}}}},"400":{"description":"Invalid request or cursor."},"401":{"description":"Invalid credential."},"403":{"description":"Missing or stale approval, unsupported record grant or insufficient live permission."},"404":{"description":"Resource or parent unavailable."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/users/{id}:
    get:
      x-seedly-oauth-scope: "users:read"
      x-seedly-standard-scope: "users:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getDirectoryUser"
      tags: ["Directory"]
      summary: "getDirectoryUser"
      description: "Location-wide Standard v2 or OAuth with fresh approval only; legacy keys and own/team/selected grants are denied. This is safe directory metadata, not agency or personal authority. No emails, phone numbers, role/permission details, credentials or team rosters are returned. Requires users:read and live users:view permission for all records. Lists active users with location access; display names never fall back to email. Returns 409 when this person has access to this location but holds too many memberships to read."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Authorized projection or minimal write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/IntegrationDirectoryUser"}}}}}},"400":{"description":"Invalid request or cursor."},"401":{"description":"Invalid credential."},"403":{"description":"Missing or stale approval, unsupported record grant or insufficient live permission."},"404":{"description":"Resource or parent unavailable."},"409":{"description":"This user has too many memberships to read through the API."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/teams:
    get:
      x-seedly-oauth-scope: "teams:read"
      x-seedly-standard-scope: "teams:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "listDirectoryTeams"
      tags: ["Directory"]
      summary: "listDirectoryTeams"
      description: "Location-wide Standard v2 or OAuth with fresh approval only; legacy keys and own/team/selected grants are denied. This is safe directory metadata, not agency or personal authority. No emails, phone numbers, role/permission details, credentials or team rosters are returned. Requires teams:read and live settings:view permission for all records. Includes this location and shared agency team metadata only."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":8192}}]
      responses: {"200":{"description":"Authorized projection or minimal write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/IntegrationDirectoryTeam"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}},"400":{"description":"Invalid request or cursor."},"401":{"description":"Invalid credential."},"403":{"description":"Missing or stale approval, unsupported record grant or insufficient live permission."},"404":{"description":"Resource or parent unavailable."},"429":{"description":"Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "teams:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: postTeams
      tags: [Directory]
      summary: Create a location team
      description: "Acts through the live role of the consenting person. Native rank, permission ceiling and containment checks apply, so an app can never grant more than that person holds, and cannot change that person's own access. Not available to Standard location keys, which have no human authority to prove. Location memberships and location roles only."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string"},"description":{"type":"string"}}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/teams/{id}:
    get:
      x-seedly-oauth-scope: "teams:read"
      x-seedly-standard-scope: "teams:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getDirectoryTeam"
      tags: ["Directory"]
      summary: "getDirectoryTeam"
      description: "Location-wide Standard v2 or OAuth with fresh approval only; legacy keys and own/team/selected grants are denied. This is safe directory metadata, not agency or personal authority. No emails, phone numbers, role/permission details, credentials or team rosters are returned. Requires teams:read and live settings:view permission for all records. Includes this location and shared agency team metadata only."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Authorized projection or minimal write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/IntegrationDirectoryTeam"}}}}}},"400":{"description":"Invalid request or cursor."},"401":{"description":"Invalid credential."},"403":{"description":"Missing or stale approval, unsupported record grant or insufficient live permission."},"404":{"description":"Resource or parent unavailable."},"429":{"description":"Rate limit exceeded."}}
    patch:
      x-seedly-oauth-scope: "teams:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: patchTeamsById
      tags: [Directory]
      summary: Update a location team
      description: "Acts through the live role of the consenting person. Native rank, permission ceiling and containment checks apply, so an app can never grant more than that person holds, and cannot change that person's own access. Not available to Standard location keys, which have no human authority to prove. Location memberships and location roles only."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string"},"description":{"type":"string"}}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "teams:delete"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: deleteTeamsById
      tags: [Directory]
      summary: Delete a location team
      description: "Acts through the live role of the consenting person. Native rank, permission ceiling and containment checks apply, so an app can never grant more than that person holds, and cannot change that person's own access. Not available to Standard location keys, which have no human authority to prove. Location memberships and location roles only."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/email-templates/{id}:
    get:
      x-seedly-oauth-scope: "templates:read"
      x-seedly-standard-scope: "templates:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getIntegrationEmailLayout
      tags: [Campaigns]
      summary: "Read a shared email layout"
      description: "Explicitly approved location-wide Standard v2 or OAuth only. Legacy API keys and own/team/selected grants cannot use this operation. Only location-owned shared layout templates are included. Private, agency, prebuilt, single-message, sequence and SMS templates are unavailable. Template permissions do not send or schedule messages. Requires templates:read and campaigns view authority. Existing layouts with unsafe content-slot positions are rejected. Includes stored bodyHtml as untrusted author-entered content, not a browser-safe preview. Internal blocks, author details and usage totals are omitted."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}]
      responses:
        '200':
          description: Authorized metadata or an idempotent write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationEmailLayout"}}}}}
        '400':
          description: Invalid request or ineligible current record state.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale approval, unsupported record restriction or revoked access.
        '404':
          description: Resource not available in this location.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "templates:write"
      x-seedly-standard-scope: "templates:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateIntegrationEmailLayout
      tags: [Campaigns]
      summary: "Update a shared email layout"
      description: "A template bound as a send default also needs the matching send scope, and one that cannot be proved unbound is refused with a conflict. Explicitly approved location-wide Standard v2 or OAuth only. Legacy API keys and own/team/selected grants cannot use this operation. Only location-owned shared layout templates are included. Private, agency, prebuilt, single-message, sequence and SMS templates are unavailable. Template permissions do not send or schedule messages. Requires templates:write and campaigns create/update authority. Allowed fields are name, subject, preheader and bodyHtml. Names must be nonblank. Supplied HTML is sanitized with the email profile and must retain exactly one {{content}} slot in HTML text, never inside attributes, markup, comments or raw-text elements. Script, iframe, object, embed and inline event-handler constructs are rejected. Sharing, owner, type, blocks and template references cannot be changed. HTTP JSON bodies are capped at 1 MiB; character limits apply separately. Requires a stable Idempotency-Key. Unknown body fields are rejected. Current authorization and target eligibility are checked before retry receipts are returned; retries do not reapply the mutation. Writes return only an identifier and created/updated receipt, not record content. Requires at least one allowed field and synchronizes the native template summary."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"name": {"type": "string", "minLength": 1, "maxLength": 255}, "subject": {"type": "string", "maxLength": 1000}, "preheader": {"type": "string", "maxLength": 200}, "bodyHtml": {"type": "string", "maxLength": 500000}}, "minProperties": 1}}}}
      responses:
        '200':
          description: Authorized metadata or an idempotent write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationValueWriteReceipt"}}}}}
        '400':
          description: Invalid request or ineligible current record state.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale approval, unsupported record restriction or revoked access.
        '404':
          description: Resource not available in this location.
        '409':
          description: Idempotency key reused with different request details.
        '413':
          description: Request body exceeds the byte limit.
        '415':
          description: Write request must use application/json.
        '429':
          description: Rate limit exceeded.
  /api/v1/email-templates:
    get:
      x-seedly-oauth-scope: "templates:read"
      x-seedly-standard-scope: "templates:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listIntegrationEmailLayouts
      tags: [Campaigns]
      summary: "List shared email layout metadata"
      description: "Explicitly approved location-wide Standard v2 or OAuth only. Legacy API keys and own/team/selected grants cannot use this operation. Only location-owned shared layout templates are included. Private, agency, prebuilt, single-message, sequence and SMS templates are unavailable. Template permissions do not send or schedule messages. Requires templates:read and campaigns view authority. Returns metadata without HTML, blocks, author details or usage totals. Cursor pages may be underfilled or empty after eligibility filtering; follow meta.cursor while hasMore is true."
      parameters: [{"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}, {"name": "cursor", "in": "query", "schema": {"type": "string", "minLength": 1, "maxLength": 8192}}]
      responses:
        '200':
          description: Authorized metadata or an idempotent write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"type": "array", "items": {"$ref": "#/components/schemas/IntegrationEmailLayoutSummary"}}, "meta": {"$ref": "#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid request or ineligible current record state.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale approval, unsupported record restriction or revoked access.
        '404':
          description: Resource not available in this location.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "templates:write"
      x-seedly-standard-scope: "templates:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createIntegrationEmailLayout
      tags: [Campaigns]
      summary: "Create a shared email layout"
      description: "Explicitly approved location-wide Standard v2 or OAuth only. Legacy API keys and own/team/selected grants cannot use this operation. Only location-owned shared layout templates are included. Private, agency, prebuilt, single-message, sequence and SMS templates are unavailable. Template permissions do not send or schedule messages. Requires templates:write and campaigns create/update authority. Allowed fields are name, subject, preheader and bodyHtml. Names must be nonblank. Supplied HTML is sanitized with the email profile and must retain exactly one {{content}} slot in HTML text, never inside attributes, markup, comments or raw-text elements. Script, iframe, object, embed and inline event-handler constructs are rejected. Sharing, owner, type, blocks and template references cannot be changed. HTTP JSON bodies are capped at 1 MiB; character limits apply separately. Requires a stable Idempotency-Key. Unknown body fields are rejected. Current authorization and target eligibility are checked before retry receipts are returned; retries do not reapply the mutation. Writes return only an identifier and created/updated receipt, not record content. Creates a shared sub-account layout and synchronizes the native template summary."
      parameters: [{"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"name": {"type": "string", "minLength": 1, "maxLength": 255}, "subject": {"type": "string", "maxLength": 1000}, "preheader": {"type": "string", "maxLength": 200}, "bodyHtml": {"type": "string", "maxLength": 500000}}, "required": ["name", "bodyHtml"]}}}}
      responses:
        '200':
          description: Authorized metadata or an idempotent write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationValueWriteReceipt"}}}}}
        '400':
          description: Invalid request or ineligible current record state.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale approval, unsupported record restriction or revoked access.
        '404':
          description: Resource not available in this location.
        '409':
          description: Idempotency key reused with different request details.
        '413':
          description: Request body exceeds the byte limit.
        '415':
          description: Write request must use application/json.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipelines/{id}/stages/reorder:
    post:
      x-seedly-oauth-scope: "pipelines:write"
      x-seedly-standard-scope: "pipelines:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: reorderIntegrationPipelineStages
      tags: [Pipelines]
      summary: "Reorder every stage in a pipeline"
      description: "Explicitly approved location-wide Standard v2 or OAuth only. Legacy API keys and own/team/selected grants cannot use this operation. Requires pipelines:write, with pipelines and deals create/update role authority. Existing pipelines additionally require live edit access through their pipeline ACL and an active approving user/membership. No owner, ACL, default-setting, deal-movement or deletion operation is included. Requires a stable Idempotency-Key. Unknown body fields are rejected. Current authorization and target eligibility are checked before retry receipts are returned; retries do not reapply the mutation. Writes return only an identifier and created/updated receipt, not record content. stageIds must contain the exact current stage set once each, in the desired order: 1-100 unique IDs. Missing, extra, foreign or duplicate stages are rejected, including on retry. Only positions change; opportunities remain in their stages."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"stageIds": {"type": "array", "minItems": 1, "maxItems": 100, "uniqueItems": true, "items": {"type": "string"}}}, "required": ["stageIds"]}}}}
      responses:
        '200':
          description: Authorized metadata or an idempotent write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationValueWriteReceipt"}}}}}
        '400':
          description: Invalid request or ineligible current record state.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale approval, unsupported record restriction or revoked access.
        '404':
          description: Resource not available in this location.
        '409':
          description: Idempotency key reused with different request details.
        '413':
          description: Request body exceeds the byte limit.
        '415':
          description: Write request must use application/json.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipeline-stages/{id}:
    patch:
      x-seedly-oauth-scope: "pipelines:write"
      x-seedly-standard-scope: "pipelines:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateIntegrationPipelineStage
      tags: [Pipelines]
      summary: "Update pipeline stage metadata"
      description: "Explicitly approved location-wide Standard v2 or OAuth only. Legacy API keys and own/team/selected grants cannot use this operation. Requires pipelines:write, with pipelines and deals create/update role authority. Existing pipelines additionally require live edit access through their pipeline ACL and an active approving user/membership. No owner, ACL, default-setting, deal-movement or deletion operation is included. Requires a stable Idempotency-Key. Unknown body fields are rejected. Current authorization and target eligibility are checked before retry receipts are returned; retries do not reapply the mutation. Writes return only an identifier and created/updated receipt, not record content. Accepts a nonempty patch of name, description, color, probability or isTerminal. The pipeline and stage position cannot change here. Updating terminal/probability metadata does not transition existing deals. Retry checks retain the original pipeline binding."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"name": {"type": "string", "minLength": 1, "maxLength": 200}, "description": {"type": "string", "maxLength": 90}, "color": {"type": "string", "pattern": "^#[a-fA-F0-9]{6}$"}, "probability": {"type": "number", "minimum": 0, "maximum": 100}, "isTerminal": {"type": "boolean"}}, "minProperties": 1}}}}
      responses:
        '200':
          description: Authorized metadata or an idempotent write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationValueWriteReceipt"}}}}}
        '400':
          description: Invalid request or ineligible current record state.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale approval, unsupported record restriction or revoked access.
        '404':
          description: Resource not available in this location.
        '409':
          description: Idempotency key reused with different request details.
        '413':
          description: Request body exceeds the byte limit.
        '415':
          description: Write request must use application/json.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "pipelines:delete"
      x-seedly-standard-scope: "pipelines:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deletePipelineStage
      tags: [Pipelines]
      summary: Delete an empty stage
      description: "Separate pipelines:delete approval. Refused while live opportunities remain in the stage. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipelines/{id}/stages:
    post:
      x-seedly-oauth-scope: "pipelines:write"
      x-seedly-standard-scope: "pipelines:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createIntegrationPipelineStage
      tags: [Pipelines]
      summary: "Append a pipeline stage"
      description: "Explicitly approved location-wide Standard v2 or OAuth only. Legacy API keys and own/team/selected grants cannot use this operation. Requires pipelines:write, with pipelines and deals create/update role authority. Existing pipelines additionally require live edit access through their pipeline ACL and an active approving user/membership. No owner, ACL, default-setting, deal-movement or deletion operation is included. Requires a stable Idempotency-Key. Unknown body fields are rejected. Current authorization and target eligibility are checked before retry receipts are returned; retries do not reapply the mutation. Writes return only an identifier and created/updated receipt, not record content. Appends after the current final stage using a server-derived position. At most 100 stages per pipeline. Name is required and trimmed; stage description is limited to 90 characters. Probability is finite from 0 through 100. Changing terminal metadata does not move or close existing deals."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"name": {"type": "string", "minLength": 1, "maxLength": 200}, "description": {"type": "string", "maxLength": 90}, "color": {"type": "string", "pattern": "^#[a-fA-F0-9]{6}$"}, "probability": {"type": "number", "minimum": 0, "maximum": 100}, "isTerminal": {"type": "boolean"}}, "required": ["name"]}}}}
      responses:
        '200':
          description: Authorized metadata or an idempotent write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationValueWriteReceipt"}}}}}
        '400':
          description: Invalid request or ineligible current record state.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale approval, unsupported record restriction or revoked access.
        '404':
          description: Resource not available in this location.
        '409':
          description: Idempotency key reused with different request details.
        '413':
          description: Request body exceeds the byte limit.
        '415':
          description: Write request must use application/json.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipelines/{id}:
    patch:
      x-seedly-oauth-scope: "pipelines:write"
      x-seedly-standard-scope: "pipelines:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateIntegrationPipeline
      tags: [Pipelines]
      summary: "Update pipeline name or description"
      description: "Explicitly approved location-wide Standard v2 or OAuth only. Legacy API keys and own/team/selected grants cannot use this operation. Requires pipelines:write, with pipelines and deals create/update role authority. Existing pipelines additionally require live edit access through their pipeline ACL and an active approving user/membership. No owner, ACL, default-setting, deal-movement or deletion operation is included. Requires a stable Idempotency-Key. Unknown body fields are rejected. Current authorization and target eligibility are checked before retry receipts are returned; retries do not reapply the mutation. Writes return only an identifier and created/updated receipt, not record content. Accepts a nonempty name/description patch only. Names are trimmed; control characters are rejected."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"name": {"type": "string", "minLength": 1, "maxLength": 200}, "description": {"type": "string", "maxLength": 5000}}, "minProperties": 1}}}}
      responses:
        '200':
          description: Authorized metadata or an idempotent write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationValueWriteReceipt"}}}}}
        '400':
          description: Invalid request or ineligible current record state.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale approval, unsupported record restriction or revoked access.
        '404':
          description: Resource not available in this location.
        '409':
          description: Idempotency key reused with different request details.
        '413':
          description: Request body exceeds the byte limit.
        '415':
          description: Write request must use application/json.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "pipelines:delete"
      x-seedly-standard-scope: "pipelines:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deletePipeline
      tags: [Pipelines]
      summary: Delete an empty pipeline
      description: "Separate pipelines:delete approval. Refused while live opportunities remain. Stages are removed; deleted opportunities keep their retention window and restore into a remaining pipeline. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/custom-values:
    get:
      x-seedly-oauth-scope: "custom-values:read"
      x-seedly-standard-scope: "custom-values:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listIntegrationCustomValues
      tags: [Contacts]
      summary: "List location custom values"
      description: "Location-wide Standard v2 or OAuth only, with fresh approval for this operation. Legacy keys and own/team/selected grants are denied. Custom values are reusable location settings. Read permission includes potentially sensitive user-stored content such as private links or API keys. Creation normalizes keys to lowercase/underscores. Updates cannot rename keys or move folders. Writes return receipts, not stored values. "
      parameters: [{"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}, {"name": "cursor", "in": "query", "schema": {"type": "string", "minLength": 1, "maxLength": 8192}}]
      responses:
        '200':
          description: Authorized resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"type": "array", "items": {"$ref": "#/components/schemas/IntegrationCustomValue"}}, "meta": {"$ref": "#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid body, path, query or idempotency key.
        '403':
          description: Missing authority, stale approval, restricted grant or stale relationship.
        '404':
          description: Record unavailable.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "custom-values:write"
      x-seedly-standard-scope: "custom-values:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createIntegrationCustomValue
      tags: [Contacts]
      summary: "Create a location custom value"
      description: "Location-wide Standard v2 or OAuth only, with fresh approval for this operation. Legacy keys and own/team/selected grants are denied. Custom values are reusable location settings. Read permission includes potentially sensitive user-stored content such as private links or API keys. Creation normalizes keys to lowercase/underscores. Updates cannot rename keys or move folders. Writes return receipts, not stored values. A stable idempotency key is required; retries recheck current authorization and target availability without reapplying the write. "
      parameters: [{"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"key": {"type": "string", "maxLength": 50}, "value": {"type": "string", "maxLength": 10000}, "description": {"type": "string", "maxLength": 5000}}, "required": ["key", "value"]}}}}
      responses:
        '200':
          description: Authorized resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationValueWriteReceipt"}}}}}
        '400':
          description: Invalid body, path, query or idempotency key.
        '403':
          description: Missing authority, stale approval, restricted grant or stale relationship.
        '404':
          description: Record unavailable.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
  /api/v1/custom-values/{id}:
    get:
      x-seedly-oauth-scope: "custom-values:read"
      x-seedly-standard-scope: "custom-values:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getIntegrationCustomValue
      tags: [Contacts]
      summary: "Read a location custom value"
      description: "Location-wide Standard v2 or OAuth only, with fresh approval for this operation. Legacy keys and own/team/selected grants are denied. Custom values are reusable location settings. Read permission includes potentially sensitive user-stored content such as private links or API keys. Creation normalizes keys to lowercase/underscores. Updates cannot rename keys or move folders. Writes return receipts, not stored values. "
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}]
      responses:
        '200':
          description: Authorized resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationCustomValue"}}}}}
        '400':
          description: Invalid body, path, query or idempotency key.
        '403':
          description: Missing authority, stale approval, restricted grant or stale relationship.
        '404':
          description: Record unavailable.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "custom-values:write"
      x-seedly-standard-scope: "custom-values:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateIntegrationCustomValue
      tags: [Contacts]
      summary: "Update a location custom value"
      description: "Location-wide Standard v2 or OAuth only, with fresh approval for this operation. Legacy keys and own/team/selected grants are denied. Custom values are reusable location settings. Read permission includes potentially sensitive user-stored content such as private links or API keys. Creation normalizes keys to lowercase/underscores. Updates cannot rename keys or move folders. Writes return receipts, not stored values. A stable idempotency key is required; retries recheck current authorization and target availability without reapplying the write. "
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"value": {"type": "string", "maxLength": 10000}, "description": {"type": "string", "maxLength": 5000}}, "minProperties": 1}}}}
      responses:
        '200':
          description: Authorized resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationValueWriteReceipt"}}}}}
        '400':
          description: Invalid body, path, query or idempotency key.
        '403':
          description: Missing authority, stale approval, restricted grant or stale relationship.
        '404':
          description: Record unavailable.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "custom-values:delete"
      x-seedly-standard-scope: "custom-values:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteCustomValue
      summary: "delete Custom Value"
      tags: [Integrations]
      description: "Requires fresh Standard v2 or OAuth operation approval and Idempotency-Key. No request body. Replays recheck authority and live parent. Contact-note deletion supports at most 100 attachment references and deletes only storage owned by the location."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Authorized projection or idempotent write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","deleted"],"properties":{"id":{"type":"string"},"deleted":{"const":true}}}}}}}},"400":{"description":"Invalid request."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked or stale operation approval."},"404":{"description":"Record or parent unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Idempotency key reused for another request."},"413":{"description":"Request body too large."},"415":{"description":"JSON content type required."}}
  /api/v1/contacts/{id}/field-values:
    get:
      x-seedly-oauth-scope: "contacts:read"
      x-seedly-standard-scope: "contacts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getIntegrationContactFieldValues
      tags: [Contacts]
      summary: "Read contact field values"
      description: "fileValues lists file fields with the exact files:read approval, with no storage reference. signatureValues says only whether a signature exists. Location-wide Standard v2 or OAuth only, with fresh approval for this operation. Legacy keys and own/team/selected grants are denied. Only active same-location scalar contact field definitions are supported; system/reserved keys and file, signature or structured field types are excluded. Values use field definition names. Supported types are text, number, monetary, date, select, radio, boolean, URL, email and phone. Nonempty numbers and booleans are not coerced; dates use a valid YYYY-MM-DD, choices must match options, and URLs use HTTP or HTTPS. PATCH merges 1-100 provided keys; null or an empty string clears a value subject to native required/dependency validation. Null remains a stored cleared value, not a property deletion. Strings are capped at 10000 characters, the merged map and returned values map at 50 KiB, and definition inspection at 1000 rows. Unknown/reserved names and malformed legacy stored maps are rejected for writes. Current definitions and regex/dependency rules are rechecked before replay. Read results omit unknown, inactive, protected, unsupported and invalidly typed stored values. Existing unrelated values remain unchanged. "
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}]
      responses:
        '200':
          description: Authorized resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationContactFieldValues"}}}}}
        '400':
          description: Invalid body, path, query or idempotency key.
        '403':
          description: Missing authority, stale approval, restricted grant or stale relationship.
        '404':
          description: Record unavailable.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "contacts:write"
      x-seedly-standard-scope: "contacts:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateIntegrationContactFieldValues
      tags: [Contacts]
      summary: "Update contact field values"
      description: "fileValues maps a file field name to a file record, or null to clear. It needs the exact files:read approval, and the file must be unlinked or linked to this contact. A signature field cannot be written. Location-wide Standard v2 or OAuth only, with fresh approval for this operation. Legacy keys and own/team/selected grants are denied. Only active same-location scalar contact field definitions are supported; system/reserved keys and file, signature or structured field types are excluded. Values use field definition names. Supported types are text, number, monetary, date, select, radio, boolean, URL, email and phone. Nonempty numbers and booleans are not coerced; dates use a valid YYYY-MM-DD, choices must match options, and URLs use HTTP or HTTPS. PATCH merges 1-100 provided keys; null or an empty string clears a value subject to native required/dependency validation. Null remains a stored cleared value, not a property deletion. Strings are capped at 10000 characters, the merged map and returned values map at 50 KiB, and definition inspection at 1000 rows. Unknown/reserved names and malformed legacy stored maps are rejected for writes. Current definitions and regex/dependency rules are rechecked before replay. Read results omit unknown, inactive, protected, unsupported and invalidly typed stored values. Existing unrelated values remain unchanged. A stable idempotency key is required; retries recheck current authorization and target availability without reapplying the write. "
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"values": {"type": "object", "minProperties": 1, "maxProperties": 100, "additionalProperties": {"type": ["string", "number", "boolean", "null"], "maxLength": 10000}}}, "required": ["values"]}}}}
      responses:
        '200':
          description: Authorized resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationValueWriteReceipt"}}}}}
        '400':
          description: Invalid body, path, query or idempotency key.
        '403':
          description: Missing authority, stale approval, restricted grant or stale relationship.
        '404':
          description: Record unavailable.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
  /api/v1/contacts/{id}/company:
    get:
      x-seedly-oauth-scope: "contacts:read"
      x-seedly-standard-scope: "contacts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getIntegrationContactCompany
      tags: [Contacts]
      summary: "Read a contact company relationship"
      description: "Location-wide Standard v2 or OAuth only, with fresh approval for this operation. Legacy keys and own/team/selected grants are denied. Requires contacts:read and companies:read; PATCH additionally requires contacts:write and companies:write. Read results contain authorized relationship references only. PATCH links, replaces or removes a company association without deleting records or changing owners. Contact counts and configured contact-update workflow behavior are preserved. "
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}]
      responses:
        '200':
          description: Authorized resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationContactCompany"}}}}}
        '400':
          description: Invalid body, path, query or idempotency key.
        '403':
          description: Missing authority, stale approval, restricted grant or stale relationship.
        '404':
          description: Record unavailable.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "contacts:write"
      x-seedly-standard-scope: "contacts:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateIntegrationContactCompany
      tags: [Contacts]
      summary: "Update a contact company relationship"
      description: "Location-wide Standard v2 or OAuth only, with fresh approval for this operation. Legacy keys and own/team/selected grants are denied. Requires contacts:read and companies:read; PATCH additionally requires contacts:write and companies:write. Read results contain authorized relationship references only. PATCH links, replaces or removes a company association without deleting records or changing owners. Contact counts and configured contact-update workflow behavior are preserved. A stable idempotency key is required. Retries and deferred workflow effects recheck authority, the original/current/destination companies, and the saved contact timestamp, company link and internal relationship revision. A changed proof is denied, including a same-clock native relationship change, rather than restoring the previous link. "
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"companyId": {"type": ["string", "null"]}}, "required": ["companyId"]}}}}
      responses:
        '200':
          description: Authorized resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationValueWriteReceipt"}}}}}
        '400':
          description: Invalid body, path, query or idempotency key.
        '403':
          description: Missing authority, stale approval, restricted grant or stale relationship.
        '404':
          description: Record unavailable.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
  /api/v1/companies/{id}/contacts:
    get:
      x-seedly-oauth-scope: "companies:read"
      x-seedly-standard-scope: "companies:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listIntegrationCompanyContacts
      tags: [Contacts]
      summary: "List company contact references"
      description: "Location-wide Standard v2 or OAuth only, with fresh approval for this operation. Legacy keys and own/team/selected grants are denied. Requires contacts:read and companies:read; PATCH additionally requires contacts:write and companies:write. Read results contain authorized relationship references only. PATCH links, replaces or removes a company association without deleting records or changing owners. Contact counts and configured contact-update workflow behavior are preserved. "
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}, {"name": "cursor", "in": "query", "schema": {"type": "string", "minLength": 1, "maxLength": 8192}}]
      responses:
        '200':
          description: Authorized resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"type": "array", "items": {"$ref": "#/components/schemas/IntegrationCompanyContact"}}, "meta": {"$ref": "#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid body, path, query or idempotency key.
        '403':
          description: Missing authority, stale approval, restricted grant or stale relationship.
        '404':
          description: Record unavailable.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-lists/{id}/members/{contactId}:
    delete:
      x-seedly-oauth-scope: "contact-lists:write"
      x-seedly-standard-scope: "contact-lists:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: administrationDeleteapiv1contactlistsidmemberscontactId
      tags: [Contacts]
      summary: "DELETE /api/v1/contact-lists/{id}/members/{contactId}"
      description: "Location-wide Standard v2 or OAuth with explicit fresh approval only. Legacy keys and own/team/selected grants are denied. Active static manual lists only, no totals or dynamic segments. Membership operations also require contacts:read. Add never restores an unsubscribe or bypasses suppression; remove unsubscribes without deleting the contact. Idempotent retries are credential/client and location bound; reuse with different details conflicts. Replays recheck authorization. "
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "contactId", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: Successful operation; data contains the safe resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationListMembershipReceipt"}}}}}
        '400':
          description: Invalid body, query, identifier or idempotency key.
        '403':
          description: Missing or revoked authority, stale approval or unsupported record restriction.
        '404':
          description: Record not found.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-lists/{id}/members:
    get:
      x-seedly-oauth-scope: "contact-lists:read"
      x-seedly-standard-scope: "contact-lists:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: administrationGetapiv1contactlistsidmembers
      tags: [Contacts]
      summary: "GET /api/v1/contact-lists/{id}/members"
      description: "Location-wide Standard v2 or OAuth with explicit fresh approval only. Legacy keys and own/team/selected grants are denied. Active static manual lists only, no totals or dynamic segments. Membership operations also require contacts:read. Add never restores an unsubscribe or bypasses suppression; remove unsubscribes without deleting the contact. "
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}, {"name": "cursor", "in": "query", "schema": {"type": "string", "maxLength": 8192, "minLength": 1}}]
      responses:
        '200':
          description: Successful operation; data contains the safe resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data", "meta"], "properties": {"data": {"type": "array", "items": {"$ref": "#/components/schemas/IntegrationListMember"}}, "meta": {"$ref": "#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid body, query, identifier or idempotency key.
        '403':
          description: Missing or revoked authority, stale approval or unsupported record restriction.
        '404':
          description: Record not found.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "contact-lists:write"
      x-seedly-standard-scope: "contact-lists:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: administrationPostapiv1contactlistsidmembers
      tags: [Contacts]
      summary: "POST /api/v1/contact-lists/{id}/members"
      description: "Location-wide Standard v2 or OAuth with explicit fresh approval only. Legacy keys and own/team/selected grants are denied. Active static manual lists only, no totals or dynamic segments. Membership operations also require contacts:read. Add never restores an unsubscribe or bypasses suppression; remove unsubscribes without deleting the contact. Idempotent retries are credential/client and location bound; reuse with different details conflicts. Replays recheck authorization. If a scheduled, sending or paused campaign targets this list, adding a member also requires campaigns:send; retries recheck it."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"contactId": {"type": "string"}}, "required": ["contactId"]}}}}
      responses:
        '200':
          description: Successful operation; data contains the safe resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationListMembershipReceipt"}}}}}
        '400':
          description: Invalid body, query, identifier or idempotency key.
        '403':
          description: Missing or revoked authority, stale approval or unsupported record restriction.
        '404':
          description: Record not found.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-lists/{id}:
    get:
      x-seedly-oauth-scope: "contact-lists:read"
      x-seedly-standard-scope: "contact-lists:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: administrationGetapiv1contactlistsid
      tags: [Contacts]
      summary: "GET /api/v1/contact-lists/{id}"
      description: "Location-wide Standard v2 or OAuth with explicit fresh approval only. Legacy keys and own/team/selected grants are denied. Active static manual lists only, no totals or dynamic segments. Membership operations also require contacts:read. Add never restores an unsubscribe or bypasses suppression; remove unsubscribes without deleting the contact. "
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}]
      responses:
        '200':
          description: Successful operation; data contains the safe resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationContactList"}}}}}
        '400':
          description: Invalid body, query, identifier or idempotency key.
        '403':
          description: Missing or revoked authority, stale approval or unsupported record restriction.
        '404':
          description: Record not found.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "contact-lists:write"
      x-seedly-standard-scope: "contact-lists:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: administrationPatchapiv1contactlistsid
      tags: [Contacts]
      summary: "PATCH /api/v1/contact-lists/{id}"
      description: "Location-wide Standard v2 or OAuth with explicit fresh approval only. Legacy keys and own/team/selected grants are denied. Active static manual lists only, no totals or dynamic segments. Membership operations also require contacts:read. Add never restores an unsubscribe or bypasses suppression; remove unsubscribes without deleting the contact. Idempotent retries are credential/client and location bound; reuse with different details conflicts. Replays recheck authorization. "
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"name": {"type": "string", "description": "Trimmed before storage; trimmed value must contain 1 to 100 characters."}, "description": {"type": "string", "maxLength": 1000}}, "minProperties": 1}}}}
      responses:
        '200':
          description: Successful operation; data contains the safe resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationUpdatedReceipt"}}}}}
        '400':
          description: Invalid body, query, identifier or idempotency key.
        '403':
          description: Missing or revoked authority, stale approval or unsupported record restriction.
        '404':
          description: Record not found.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-lists:
    get:
      x-seedly-oauth-scope: "contact-lists:read"
      x-seedly-standard-scope: "contact-lists:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: administrationGetapiv1contactlists
      tags: [Contacts]
      summary: "GET /api/v1/contact-lists"
      description: "Location-wide Standard v2 or OAuth with explicit fresh approval only. Legacy keys and own/team/selected grants are denied. Active static manual lists only, no totals or dynamic segments. Membership operations also require contacts:read. Add never restores an unsubscribe or bypasses suppression; remove unsubscribes without deleting the contact. "
      parameters: [{"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}, {"name": "cursor", "in": "query", "schema": {"type": "string", "maxLength": 8192, "minLength": 1}}]
      responses:
        '200':
          description: Successful operation; data contains the safe resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data", "meta"], "properties": {"data": {"type": "array", "items": {"$ref": "#/components/schemas/IntegrationContactList"}}, "meta": {"$ref": "#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid body, query, identifier or idempotency key.
        '403':
          description: Missing or revoked authority, stale approval or unsupported record restriction.
        '404':
          description: Record not found.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "contact-lists:write"
      x-seedly-standard-scope: "contact-lists:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: administrationPostapiv1contactlists
      tags: [Contacts]
      summary: "POST /api/v1/contact-lists"
      description: "Location-wide Standard v2 or OAuth with explicit fresh approval only. Legacy keys and own/team/selected grants are denied. Active static manual lists only, no totals or dynamic segments. Membership operations also require contacts:read. Add never restores an unsubscribe or bypasses suppression; remove unsubscribes without deleting the contact. Idempotent retries are credential/client and location bound; reuse with different details conflicts. Replays recheck authorization. "
      parameters: [{"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"name": {"type": "string", "description": "Trimmed before storage; trimmed value must contain 1 to 100 characters."}, "description": {"type": "string", "maxLength": 1000}}, "required": ["name"]}}}}
      responses:
        '200':
          description: Successful operation; data contains the safe resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationCreatedId"}}}}}
        '400':
          description: Invalid body, query, identifier or idempotency key.
        '403':
          description: Missing or revoked authority, stale approval or unsupported record restriction.
        '404':
          description: Record not found.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
  /api/v1/custom-fields/{id}:
    get:
      x-seedly-oauth-scope: "custom-fields:read"
      x-seedly-standard-scope: "custom-fields:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: administrationGetapiv1customfieldsid
      tags: [Contacts]
      summary: "GET /api/v1/custom-fields/{id}"
      description: "Location-wide Standard v2 or OAuth with explicit fresh approval only. Legacy keys and own/team/selected grants are denied. Contact field definitions only. Creation cannot use reserved field names. PATCH changes label only; no type, options, required-state or identifier changes. "
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}]
      responses:
        '200':
          description: Successful operation; data contains the safe resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationContactField"}}}}}
        '400':
          description: Invalid body, query, identifier or idempotency key.
        '403':
          description: Missing or revoked authority, stale approval or unsupported record restriction.
        '404':
          description: Record not found.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "custom-fields:write"
      x-seedly-standard-scope: "custom-fields:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: administrationPatchapiv1customfieldsid
      tags: [Contacts]
      summary: "PATCH /api/v1/custom-fields/{id}"
      description: "Location-wide Standard v2 or OAuth with explicit fresh approval only. Legacy keys and own/team/selected grants are denied. Contact field definitions only. Creation cannot use reserved field names. PATCH changes label only; no type, options, required-state or identifier changes. Idempotent retries are credential/client and location bound; reuse with different details conflicts. Replays recheck authorization. "
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"label": {"type": "string", "minLength": 1, "maxLength": 200, "description": "Nonblank; control characters are rejected."}}, "required": ["label"], "minProperties": 1}}}}
      responses:
        '200':
          description: Successful operation; data contains the safe resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationContactField"}}}}}
        '400':
          description: Invalid body, query, identifier or idempotency key.
        '403':
          description: Missing or revoked authority, stale approval or unsupported record restriction.
        '404':
          description: Record not found.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
  /api/v1/custom-fields:
    get:
      x-seedly-oauth-scope: "custom-fields:read"
      x-seedly-standard-scope: "custom-fields:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: administrationGetapiv1customfields
      tags: [Contacts]
      summary: "GET /api/v1/custom-fields"
      description: "Location-wide Standard v2 or OAuth with explicit fresh approval only. Legacy keys and own/team/selected grants are denied. Contact field definitions only. Creation cannot use reserved field names. PATCH changes label only; no type, options, required-state or identifier changes. "
      parameters: [{"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}, {"name": "cursor", "in": "query", "schema": {"type": "string", "maxLength": 8192, "minLength": 1}}]
      responses:
        '200':
          description: Successful operation; data contains the safe resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data", "meta"], "properties": {"data": {"type": "array", "items": {"$ref": "#/components/schemas/IntegrationContactField"}}, "meta": {"$ref": "#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid body, query, identifier or idempotency key.
        '403':
          description: Missing or revoked authority, stale approval or unsupported record restriction.
        '404':
          description: Record not found.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "custom-fields:write"
      x-seedly-standard-scope: "custom-fields:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: administrationPostapiv1customfields
      tags: [Contacts]
      summary: "POST /api/v1/custom-fields"
      description: "Location-wide Standard v2 or OAuth with explicit fresh approval only. Legacy keys and own/team/selected grants are denied. Contact field definitions only. Creation cannot use reserved field names. PATCH changes label only; no type, options, required-state or identifier changes. Idempotent retries are credential/client and location bound; reuse with different details conflicts. Replays recheck authorization. "
      parameters: [{"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"name": {"type": "string", "minLength": 1, "maxLength": 100, "pattern": "^[A-Za-z0-9][A-Za-z0-9_\\- ]{0,99}$", "description": "Reserved system identity, owner and consent keys are rejected. Existing inactive definitions still reserve their names."}, "label": {"type": "string", "minLength": 1, "maxLength": 200, "description": "Nonblank; control characters are rejected."}, "fieldType": {"type": "string", "enum": ["text", "number", "date", "select", "boolean", "url", "email", "phone", "monetary", "file", "signature", "radio", "textbox_list"]}, "options": {"type": "array", "items": {"type": "string", "minLength": 1, "maxLength": 200}, "minItems": 1, "maxItems": 100, "uniqueItems": true, "description": "Required for select/radio, forbidden for other types. Each option must be nonblank and contain no control characters."}}, "required": ["name", "label", "fieldType"]}}}}
      responses:
        '200':
          description: Successful operation; data contains the safe resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationContactField"}}}}}
        '400':
          description: Invalid body, query, identifier or idempotency key.
        '403':
          description: Missing or revoked authority, stale approval or unsupported record restriction.
        '404':
          description: Record not found.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
  /api/v1/tags/{id}:
    get:
      x-seedly-oauth-scope: "tags:read"
      x-seedly-standard-scope: "tags:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: administrationGetapiv1tagsid
      tags: [Contacts]
      summary: "GET /api/v1/tags/{id}"
      description: "Location-wide Standard v2 or OAuth with explicit fresh approval only. Legacy keys and own/team/selected grants are denied. No usage counts or tag rename. PATCH accepts color and description only. "
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}]
      responses:
        '200':
          description: Successful operation; data contains the safe resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationTag"}}}}}
        '400':
          description: Invalid body, query, identifier or idempotency key.
        '403':
          description: Missing or revoked authority, stale approval or unsupported record restriction.
        '404':
          description: Record not found.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "tags:write"
      x-seedly-standard-scope: "tags:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: administrationPatchapiv1tagsid
      tags: [Contacts]
      summary: "PATCH /api/v1/tags/{id}"
      description: "Location-wide Standard v2 or OAuth with explicit fresh approval only. Legacy keys and own/team/selected grants are denied. No usage counts or tag rename. PATCH accepts color and description only. Idempotent retries are credential/client and location bound; reuse with different details conflicts. Replays recheck authorization. "
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"color": {"type": "string", "pattern": "^(?:|#[0-9a-fA-F]{6}(?:[0-9a-fA-F]{2})?)$"}, "description": {"type": "string", "maxLength": 500}}, "minProperties": 1}}}}
      responses:
        '200':
          description: Successful operation; data contains the safe resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationTag"}}}}}
        '400':
          description: Invalid body, query, identifier or idempotency key.
        '403':
          description: Missing or revoked authority, stale approval or unsupported record restriction.
        '404':
          description: Record not found.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "tags:delete"
      x-seedly-standard-scope: "tags:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteIntegrationTag
      summary: "delete Integration Tag"
      tags: [Integrations]
      description: "Explicitly approved location-wide tag operation. Rename requires tags:write; delete requires tags:delete; merge requires both. Every operation additionally requires contacts:write and opportunities:write with access to all location pipelines. Uses native asynchronous contact/opportunity tag rewrites. Idempotency-Key required; no new rewrite can start while another is active. Response acknowledges accepted cleanup, which continues after credential revocation. Legacy keys and restricted grants are denied. Native UI and integration rewrites share the same serialization guard. A busy rejection commits no mutation or receipt; retry after cleanup finishes. New writes and receipt retries recheck current pipeline ACLs. This acknowledges acceptance, not background completion."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Authorized projection or idempotent write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","deleted"],"properties":{"id":{"type":"string"},"deleted":{"const":true}}}}}}}},"400":{"description":"Invalid request or another tag rewrite is in progress. Wait for cleanup to finish, then retry with the same Idempotency-Key."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked or stale operation approval."},"404":{"description":"Record or parent unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Idempotency key reused for another request."},"413":{"description":"Request body too large."},"415":{"description":"JSON content type required."}}
  /api/v1/tags:
    get:
      x-seedly-oauth-scope: "tags:read"
      x-seedly-standard-scope: "tags:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: administrationGetapiv1tags
      tags: [Contacts]
      summary: "GET /api/v1/tags"
      description: "Location-wide Standard v2 or OAuth with explicit fresh approval only. Legacy keys and own/team/selected grants are denied. No usage counts or tag rename. PATCH accepts color and description only. "
      parameters: [{"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}, {"name": "cursor", "in": "query", "schema": {"type": "string", "maxLength": 8192, "minLength": 1}}]
      responses:
        '200':
          description: Successful operation; data contains the safe resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data", "meta"], "properties": {"data": {"type": "array", "items": {"$ref": "#/components/schemas/IntegrationTag"}}, "meta": {"$ref": "#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid body, query, identifier or idempotency key.
        '403':
          description: Missing or revoked authority, stale approval or unsupported record restriction.
        '404':
          description: Record not found.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "tags:write"
      x-seedly-standard-scope: "tags:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: administrationPostapiv1tags
      tags: [Contacts]
      summary: "POST /api/v1/tags"
      description: "Location-wide Standard v2 or OAuth with explicit fresh approval only. Legacy keys and own/team/selected grants are denied. No usage counts or tag rename. PATCH accepts color and description only. Idempotent retries are credential/client and location bound; reuse with different details conflicts. Replays recheck authorization. "
      parameters: [{"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"name": {"type": "string", "maxLength": 50, "minLength": 1, "description": "Nonblank; control characters are rejected. Stored exactly as supplied."}, "color": {"type": "string", "pattern": "^(?:|#[0-9a-fA-F]{6}(?:[0-9a-fA-F]{2})?)$"}, "description": {"type": "string", "maxLength": 500}}, "required": ["name"]}}}}
      responses:
        '200':
          description: Successful operation; data contains the safe resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationTag"}}}}}
        '400':
          description: Invalid body, query, identifier or idempotency key.
        '403':
          description: Missing or revoked authority, stale approval or unsupported record restriction.
        '404':
          description: Record not found.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
  /api/v1/companies:
    get:
      x-seedly-oauth-scope: "companies:read"
      x-seedly-standard-scope: "companies:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listIntegrationCompanies
      tags: [Contacts]
      summary: List company profiles
      description: >-
        Requires freshly approved companies:read on a location-wide Standard v2 key or OAuth grant.
        Legacy keys and own/team/selected grants are denied. No writes, attachment downloads,
        linked-contact associations or internal author metadata are included.
      parameters:
        - { name: limit, in: query, schema: { type: integer, minimum: 1, maximum: 100, default: 50 } }
        - { name: cursor, in: query, schema: { type: string, maxLength: 8192 } }
      responses:
        '200':
          description: Company profile data with ISO timestamps; excludes internal notes, custom fields and contact associations.
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data: { type: array, items: { $ref: '#/components/schemas/CompanyProfile' } }
                  meta: { $ref: '#/components/schemas/ProfileReadPage' }
        '400':
          description: Invalid ID, query parameter, limit or cursor
        '403':
          description: Missing permission, stale approval or unsupported record restriction
        '404':
          description: Company not accessible in this location
        '429':
          description: Read rate limit exceeded
    post:
      x-seedly-oauth-scope: "companies:write"
      x-seedly-standard-scope: "companies:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: administrationPostapiv1companies
      tags: [Contacts]
      summary: "POST /api/v1/companies"
      description: "Location-wide Standard v2 or OAuth with explicit fresh approval only. Legacy keys and own/team/selected grants are denied. Profile fields only; no owner, contact association, notes or custom-field writes. Idempotent retries are credential/client and location bound; reuse with different details conflicts. Replays recheck authorization. "
      parameters: [{"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"name": {"type": "string"}, "domain": {"type": "string"}, "phone": {"type": "string"}, "email": {"type": "string"}, "website": {"type": "string"}, "industry": {"type": "string"}, "addressLine1": {"type": "string"}, "addressLine2": {"type": "string"}, "city": {"type": "string"}, "state": {"type": "string"}, "postalCode": {"type": "string"}, "country": {"type": "string"}, "size": {"type": "string", "enum": ["1-10", "11-50", "51-200", "201-500", "501-1000", "1001+"]}}, "required": ["name"]}}}}
      responses:
        '200':
          description: Successful operation; data contains the safe resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationCreatedReceipt"}}}}}
        '400':
          description: Invalid body, query, identifier or idempotency key.
        '403':
          description: Missing or revoked authority, stale approval or unsupported record restriction.
        '404':
          description: Record not found.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
  /api/v1/companies/{id}:
    delete:
      x-seedly-oauth-scope: "companies:delete"
      x-seedly-standard-scope: "companies:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteIntegrationCompany
      tags: [Contacts]
      summary: Permanently remove a company
      description: Fresh location-wide companies:delete approval and Idempotency-Key required. Native removal does not cascade contacts, notes, or other linked records. Replays recheck current authority and confirm the company remains absent. Legacy keys and restricted grants are denied. No request body.
      parameters: [{name: id, in: path, required: true, schema: {type: string}}, {name: Idempotency-Key, in: header, required: true, schema: {type: string, pattern: '^[A-Za-z0-9._:-]{8,128}$'}}]
      responses:
        '200':
          description: Safe deletion receipt.
          content: {application/json: {schema: {type: object, properties: {data: {type: object, required: [id, deleted], properties: {id: {type: string}, deleted: {const: true}}}}}}}
        '400': {description: Invalid request or missing idempotency key.}
        '403': {description: Missing current operation approval.}
        '404': {description: Company unavailable.}
        '409': {description: Conflicting idempotency key.}
        '429': {description: Rate limit exceeded.}
    get:
      x-seedly-oauth-scope: "companies:read"
      x-seedly-standard-scope: "companies:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getIntegrationCompany
      tags: [Contacts]
      summary: Read a company profile
      description: >-
        Requires freshly approved companies:read on a location-wide Standard v2 key or OAuth grant.
        Legacy keys and own/team/selected grants are denied. No writes, attachment downloads,
        linked-contact associations or internal author metadata are included.
      parameters:
        - { name: id, in: path, required: true, schema: { type: string } }
      responses:
        '200':
          description: Company profile data with ISO timestamps; excludes internal notes, custom fields and contact associations.
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data: { $ref: '#/components/schemas/CompanyProfile' }
        '400':
          description: Invalid ID, query parameter, limit or cursor
        '403':
          description: Missing permission, stale approval or unsupported record restriction
        '404':
          description: Company not accessible in this location
        '429':
          description: Read rate limit exceeded
    patch:
      x-seedly-oauth-scope: "companies:write"
      x-seedly-standard-scope: "companies:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: administrationPatchapiv1companiesid
      tags: [Contacts]
      summary: "PATCH /api/v1/companies/{id}"
      description: "Location-wide Standard v2 or OAuth with explicit fresh approval only. Legacy keys and own/team/selected grants are denied. Profile fields only; no owner, contact association, notes or custom-field writes. Idempotent retries are credential/client and location bound; reuse with different details conflicts. Replays recheck authorization. "
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"name": {"type": "string"}, "domain": {"type": "string"}, "phone": {"type": "string"}, "email": {"type": "string"}, "website": {"type": "string"}, "industry": {"type": "string"}, "addressLine1": {"type": "string"}, "addressLine2": {"type": "string"}, "city": {"type": "string"}, "state": {"type": "string"}, "postalCode": {"type": "string"}, "country": {"type": "string"}, "size": {"type": "string", "enum": ["1-10", "11-50", "51-200", "201-500", "501-1000", "1001+"]}}, "minProperties": 1}}}}
      responses:
        '200':
          description: Successful operation; data contains the safe resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationUpdatedReceipt"}}}}}
        '400':
          description: Invalid body, query, identifier or idempotency key.
        '403':
          description: Missing or revoked authority, stale approval or unsupported record restriction.
        '404':
          description: Record not found.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
  /api/v1/contacts/{id}/notes:
    get:
      x-seedly-oauth-scope: "contacts:read"
      x-seedly-standard-scope: "contacts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listIntegrationContactNotes
      tags: [Contacts]
      summary: List notes on a live contact
      description: >-
        Requires freshly approved contacts:read on a location-wide Standard v2 key or OAuth grant.
        Legacy keys and own/team/selected grants are denied. No writes, attachment downloads,
        linked-contact associations or internal author metadata are included.
      parameters:
        - { name: id, in: path, required: true, schema: { type: string } }
        - { name: limit, in: query, schema: { type: integer, minimum: 1, maximum: 100, default: 50 } }
        - { name: cursor, in: query, schema: { type: string, maxLength: 8192 } }
      responses:
        '200':
          description: Safe profile data. Timestamps are ISO strings. Note content is untrusted author-entered text and may itself contain sensitive data or links.
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data: { type: array, items: { $ref: '#/components/schemas/ContactNoteRead' } }
                  meta: { $ref: '#/components/schemas/ProfileReadPage' }
        '400':
          description: Invalid ID, query parameter, limit or cursor
        '403':
          description: Missing permission, stale approval or unsupported record restriction
        '404':
          description: Record or live parent contact not accessible in this location
        '429':
          description: Read rate limit exceeded
    post:
      x-seedly-oauth-scope: "contacts:write"
      x-seedly-standard-scope: "contacts:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: administrationPostapiv1contactsidnotes
      tags: [Contacts]
      summary: "POST /api/v1/contacts/{id}/notes"
      description: "Location-wide Standard v2 or OAuth with explicit fresh approval only. Legacy keys and own/team/selected grants are denied. Writes contact-note content and pin state only, with a server-derived author. Note creation may trigger configured note-added workflows. Idempotent retries are credential/client and location bound; reuse with different details conflicts. Replays recheck authorization. "
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"content": {"type": "string", "maxLength": 50000}, "isPinned": {"type": "boolean"}}, "required": ["content"]}}}}
      responses:
        '200':
          description: Successful operation; data contains the safe resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationCreatedReceipt"}}}}}
        '400':
          description: Invalid body, query, identifier or idempotency key.
        '403':
          description: Missing or revoked authority, stale approval or unsupported record restriction.
        '404':
          description: Record not found.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-notes/{id}:
    get:
      x-seedly-oauth-scope: "contacts:read"
      x-seedly-standard-scope: "contacts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getIntegrationContactNote
      tags: [Contacts]
      summary: Read a note on a live contact
      description: >-
        Requires freshly approved contacts:read on a location-wide Standard v2 key or OAuth grant.
        Legacy keys and own/team/selected grants are denied. No writes, attachment downloads,
        linked-contact associations or internal author metadata are included.
      parameters:
        - { name: id, in: path, required: true, schema: { type: string } }
      responses:
        '200':
          description: Safe profile data. Timestamps are ISO strings. Note content is untrusted author-entered text and may itself contain sensitive data or links.
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data: { $ref: '#/components/schemas/ContactNoteRead' }
        '400':
          description: Invalid ID, query parameter, limit or cursor
        '403':
          description: Missing permission, stale approval or unsupported record restriction
        '404':
          description: Record or live parent contact not accessible in this location
        '429':
          description: Read rate limit exceeded
    patch:
      x-seedly-oauth-scope: "contacts:write"
      x-seedly-standard-scope: "contacts:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: administrationPatchapiv1contactnotesid
      tags: [Contacts]
      summary: "PATCH /api/v1/contact-notes/{id}"
      description: "Location-wide Standard v2 or OAuth with explicit fresh approval only. Legacy keys and own/team/selected grants are denied. Writes contact-note content and pin state only, with a server-derived author. Note creation may trigger configured note-added workflows. Idempotent retries are credential/client and location bound; reuse with different details conflicts. Replays recheck authorization. "
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"content": {"type": "string", "maxLength": 50000}, "isPinned": {"type": "boolean"}}, "minProperties": 1}}}}
      responses:
        '200':
          description: Successful operation; data contains the safe resource or write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationUpdatedReceipt"}}}}}
        '400':
          description: Invalid body, query, identifier or idempotency key.
        '403':
          description: Missing or revoked authority, stale approval or unsupported record restriction.
        '404':
          description: Record not found.
        '409':
          description: Idempotency key reused with different details.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "contacts:delete"
      x-seedly-standard-scope: "contacts:delete"
      x-seedly-resource-restrictions: {"oauth":["location","record_grant_required"],"standard":["location"]}
      operationId: deleteContactNote
      summary: "delete Contact Note"
      tags: [Integrations]
      description: "Requires fresh contacts:delete operation approval and Idempotency-Key; no request body. Legacy keys are denied. OAuth requires an own/team/selected record grant on the live parent contact; Standard v2 may use location-wide or reviewed restricted authority. Parent access alone does not permit deleting another author's note: restricted credentials require both approved and current all-record contacts deletion permission for other authors. Replays recheck the live parent, current grant, and persisted author proof. At most 100 attachment references are accepted; larger arrays fail atomically. Cleanup deletes only storage owned by the location, deduplicates references, and never returns attachment IDs or note content."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Authorized projection or idempotent write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","deleted"],"properties":{"id":{"type":"string"},"deleted":{"const":true}}}}}}}},"400":{"description":"Invalid request."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked or stale operation approval."},"404":{"description":"Record or parent unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Idempotency key reused for another request."},"413":{"description":"Request body too large."},"415":{"description":"JSON content type required."}}
  /api/v1/connected-apps/contacts/caller-id:
    post:
      x-seedly-oauth-scope: "contacts:read"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      summary: "Resolve an exact caller number to a greeting name"
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [phone]
              additionalProperties: false
              properties:
                phone: { type: string }
      responses:
        "200": { description: "One active contact's ID and name" }
  /api/v1/connected-apps/contacts/context:
    post:
      x-seedly-oauth-scope: "contacts:read"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      summary: "Read an explicitly scoped contact's tags, fields and stage"
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [contactId]
              additionalProperties: false
              properties:
                contactId: { type: string }
      responses:
        "200": { description: "Contact context" }
  /api/v1/connected-apps/calls/grade:
    post:
      x-seedly-oauth-scope: "calls:write"
      x-seedly-resource-restrictions: {"oauth":["integration_owned"]}
      summary: "Grade a call previously reported by this application"
      security:
        - bearerAuth: []
      parameters:
        - name: Idempotency-Key
          in: header
          required: true
          schema: { type: string }
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [callLogId, overallScore, summary]
              additionalProperties: false
              properties:
                callLogId: { type: string }
                overallScore: { type: integer, minimum: 0, maximum: 100 }
                summary: { type: string, maxLength: 2000 }
                coachingNotes: { type: string, maxLength: 4000 }
                criteria: { type: array, maxItems: 10, items: { type: object } }
      responses:
        "200": { description: "Stored call grade" }
  /api/v1/connected-apps/calendars/holds:
    post:
      x-seedly-oauth-scope: "appointments:write"
      x-seedly-standard-scope: "appointments:write"
      x-seedly-resource-restrictions: {"oauth":["integration_owned","bookable_slots"],"standard":["integration_owned","bookable_slots"]}
      summary: "Hold up to two bookable times for five minutes"
      description: "OAuth connections and Standard v2 keys with this exact approved operation. Legacy keys and restricted record grants are refused. The holder is the connected app or the key itself. A Standard key consumes its hold by sending holdExternalCallId to POST /api/v1/calendars/appointments."
      security:
        - bearerAuth: []
      parameters:
        - name: Idempotency-Key
          in: header
          required: true
          schema: { type: string }
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [appointmentTypeId, externalCallId, slots]
              additionalProperties: false
              properties:
                appointmentTypeId: { type: string }
                externalCallId: { type: string }
                slots:
                  type: array
                  minItems: 1
                  maxItems: 2
                  items:
                    type: object
                    required: [startTime, endTime]
                    additionalProperties: false
                    properties:
                      startTime: { type: integer, format: int64, description: "Unix milliseconds" }
                      endTime: { type: integer, format: int64, description: "Unix milliseconds" }
      responses:
        "200": { description: "Held times and expiry" }
  /api/v1/connected-apps/conversations/sms:
    post:
      x-seedly-oauth-scope: "messages:send"
      x-seedly-resource-restrictions: {"oauth":["configured_sender","contact_recipient"]}
      summary: "Send a consent-checked SMS to a contact"
      security:
        - bearerAuth: []
      parameters:
        - name: Idempotency-Key
          in: header
          required: true
          schema: { type: string }
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [contactId, body]
              additionalProperties: false
              properties:
                contactId: { type: string }
                body: { type: string, maxLength: 1600 }
                externalCallId: { type: string }
      responses:
        "200": { description: "Queued message" }
  /api/v1/connected-apps/conversations/replies/{messageId}:
    get:
      x-seedly-oauth-scope: "messages:replies:read"
      x-seedly-resource-restrictions: {"oauth":["integration_owned"]}
      summary: "Reserved app-owned SMS reply read"
      description: |
        The scope and route are reserved for app-owned SMS replies. This
        operation is held in 5.10.0 while native send paths and provider sender
        confirmation are audited. An approved OAuth grant still receives 403;
        no reply content is returned. Legacy keys and CloseBot are unaffected.
      security:
        - bearerAuth: []
      parameters:
        - name: messageId
          in: path
          required: true
          schema: { type: string }
      responses:
        "403": { description: "App-owned reply reads are held" }
        "429": { description: "Rate limit exceeded" }
  /api/v1/connected-apps/workflows/enroll:
    post:
      x-seedly-oauth-scope: "workflows:execute"
      x-seedly-resource-restrictions: {"oauth":["approved_workflows"]}
      summary: "Start one selected inbound-webhook workflow"
      security:
        - bearerAuth: []
      parameters:
        - name: Idempotency-Key
          in: header
          required: true
          schema: { type: string }
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [contactId, workflowId, phase, externalCallId]
              additionalProperties: false
              properties:
                contactId: { type: string }
                workflowId: { type: string }
                phase: { type: string, enum: [during_call, after_call] }
                externalCallId: { type: string }
                eventData: { type: object, additionalProperties: true }
      responses:
        "200": { description: "Accepted workflow event" }
  /api/v1/connected-apps/billing/usage:
    post:
      x-seedly-oauth-scope: "billing:usage:write"
      x-seedly-resource-restrictions: {"oauth":["integration_owned"]}
      summary: "Record agency-priced usage for a reported call"
      security:
        - bearerAuth: []
      parameters:
        - name: Idempotency-Key
          in: header
          required: true
          schema: { type: string }
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [callLogId, externalCallId, billedMinutes]
              additionalProperties: false
              properties:
                callLogId: { type: string }
                externalCallId: { type: string }
                billedMinutes: { type: integer, minimum: 1, maximum: 1440 }
      responses:
        "200": { description: "Usage receipt" }
  /api/v1/connected-apps/phone-numbers/inbound-config:
    put:
      x-seedly-oauth-scope: "phone-numbers:routing:write"
      x-seedly-resource-restrictions: {"oauth":["approved_phone_pools","approved_destinations"]}
      summary: "Set an approved forwarding destination on a tracking pool"
      security:
        - bearerAuth: []
      parameters:
        - name: Idempotency-Key
          in: header
          required: true
          schema: { type: string }
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [poolId, forwardToNumber]
              additionalProperties: false
              properties:
                poolId: { type: string }
                forwardToNumber: { type: string, pattern: "^\\+[1-9][0-9]{7,14}$" }
      responses:
        "200": { description: "Updated forwarding configuration" }
  /api/v1/connected-apps/calls/context:
    post:
      x-seedly-oauth-scope: "calls:read"
      x-seedly-resource-restrictions: {"oauth":["integration_owned"]}
      summary: "Redeem an installation-issued forwarded-call context code"
      description: "OAuth only. Binds a short-lived, installation-issued code to the app externalCallId.
        Codes are specific to app, location and consent grant. Five-minute expiry, safe matching
        retries. No public issuer; forwarding transport is not wired yet and needs an authenticated
        installation adapter. This proves call correlation only, never caller identity or permission
        to transfer/control calls."
      security:
        - bearerAuth: []
      parameters:
        - name: "Idempotency-Key"
          in: "header"
          required: true
          schema:
            type: "string"
            pattern: "^[A-Za-z0-9._:-]{8,128}$"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ConnectedAppCallContextRequest"
      responses:
        "200":
          description: "Bound call context or matching retry before expiry"
          content:
            application/json:
              schema:
                type: "object"
                required:
                  - "data"
                properties:
                  data:
                    $ref: "#/components/schemas/ConnectedAppCallContextReceipt"
        "400":
          description: "Malformed or unknown fields or invalid Idempotency-Key"
        "401":
          description: "Invalid access token"
        "403":
          description: "Missing scope or revoked connection"
        "404":
          description: "Code expired, rotated, unavailable or bound to another app, location, grant or carrier
            call"
        "409":
          description: "Changed redemption, reused app session ID, or call already bound/reported"
        "413":
          description: "Declared body exceeds 16 KiB"
        "429":
          description: "API rate limit reached"
        "500":
          description: "Retry with the original body and key before expiry"
  /api/v1/connected-apps/calls/recording:
    post:
      x-seedly-oauth-scope: "calls:recordings:write"
      x-seedly-resource-restrictions: {"oauth":["integration_owned"]}
      summary: "Upload final audio for a call this app reported"
      description: "OAuth only. Raw MP3 or WAV bytes, at most 8 MiB. Requires an accepted call report by
        this app and location. One immutable recording per app/call/leg. Exact byte, content type and call
        ID retries return the same receipt. No URL downloads, multipart, chunks, AI processing or
        vendor-side deletion. Existing grants must explicitly approve this scope."
      security:
        - bearerAuth: []
      parameters:
        - name: "Idempotency-Key"
          in: "header"
          required: true
          schema:
            type: "string"
            pattern: "^[A-Za-z0-9._:-]{8,128}$"
        - name: "X-Call-Log-Id"
          in: "header"
          required: true
          schema:
            type: "string"
            minLength: 1
            maxLength: 128
        - name: "X-Recording-Leg"
          in: "header"
          required: false
          description: "Omit for the primary AI receptionist leg. Warm transfer audio is a separate leg."
          schema:
            type: "string"
            enum: ["ai_receptionist", "warm_transfer"]
      requestBody:
        required: true
        content:
          audio/mpeg:
            schema:
              type: "string"
              format: "binary"
          audio/wav:
            schema:
              type: "string"
              format: "binary"
      responses:
        "200":
          description: "Accepted recording or matching retry"
          content:
            application/json:
              schema:
                type: "object"
                required:
                  - "data"
                properties:
                  data:
                    $ref: "#/components/schemas/ConnectedAppRecordingReceipt"
        "400":
          description: "Malformed headers or audio signature"
        "401":
          description: "Invalid access token"
        "403":
          description: "Missing scope or revoked connection"
        "404":
          description: "Call, contact or recording unavailable, wrong reporting app, or expired retention"
        "409":
          description: "Changed retry or recording already submitted"
        "413":
          description: "Upload exceeds 8 MiB"
        "415":
          description: "Only audio/mpeg and audio/wav are accepted"
        "429":
          description: "API rate limit reached"
        "500":
          description: "Retry with the same key, headers and bytes"
  /api/v1/connected-apps/calls/transcript:
    post:
      x-seedly-oauth-scope: "calls:transcripts:write"
      x-seedly-resource-restrictions: {"oauth":["integration_owned"]}
      summary: "Submit a final transcript for a call this app reported"
      description: "OAuth only. Requires this client to have reported the same call. One final transcript
        per app and call; immutable and independently retryable from the summary. Whole UTF-8 JSON
        body is limited to 128 KiB, including streamed requests. Text is retained separately from
        native recording-backed transcripts. No AI charges, grading, workflow triggers, recording
        download or new inbox entry. Retention/deletion prevents re-upload. See the connection
        contract for full timing, retention and replay semantics."
      security:
        - bearerAuth: []
      parameters:
        - name: "Idempotency-Key"
          in: "header"
          required: true
          schema:
            type: "string"
            pattern: "^[A-Za-z0-9._:-]{8,128}$"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ConnectedAppTranscriptRequest"
      responses:
        "200":
          description: "Accepted transcript or matching retry"
          content:
            application/json:
              schema:
                type: "object"
                required:
                  - "data"
                properties:
                  data:
                    $ref: "#/components/schemas/ConnectedAppTranscriptReceipt"
        "400":
          $ref: "#/components/responses/ValidationError"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          description: "Missing transcript scope or inactive grant"
        "404":
          description: "Unavailable call or transcript; includes another app, location, deleted contact, and
            expired retention"
        "409":
          description: "Changed retry payload or another transcript already submitted"
        "413":
          description: "Declared body length exceeds 128 KiB"
        "429":
          description: "Rate limited; honor Retry-After"
        "500":
          description: "Retry with the original key and payload"
  /api/v1/connected-apps/contacts/lookup:
    post:
      x-seedly-oauth-scope: "contacts:read"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      summary: "Lookup one contact"
      description: "Known CRM contact ID or two matching identifiers; all supplied details must match one
        active contact. Email matching preserves stored spelling. No bulk search. OAuth only; API keys
        are refused. Strict JSON body limit is 16 KiB. See the connected-apps contract for replay,
        normalization and correlation requirements."
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ConnectedAppContactLookup"
      responses:
        "200":
          description: "Successful result"
          content:
            application/json:
              schema:
                type: "object"
                additionalProperties: false
                properties:
                  data:
                    $ref: "#/components/schemas/ConnectedAppContact"
                required:
                  - "data"
        "400":
          $ref: "#/components/responses/ValidationError"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          description: "Missing permission or wrong credential type"
        "404":
          description: "Contact or call unavailable; includes deleted, ambiguous and inaccessible records"
        "409":
          description: "Conflict or changed retry payload"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "429":
          description: "Rate limited; honor Retry-After"
        "500":
          description: "Failed operation; retry a write with its original key and payload"
  /api/v1/connected-apps/contacts/create:
    post:
      x-seedly-oauth-scope: "contacts:write"
      x-seedly-resource-restrictions: {"oauth":["location","no_consent_or_assignment"]}
      summary: "Create a contact without merging"
      description: "New contacts only. Duplicate email or phone, including deleted records, returns 409
        without disclosing an ID. Normal CRM contact workflow and default-list rules apply. OAuth
        only; API keys are refused. Strict JSON body limit is 16 KiB. See the connected-apps contract
        for replay, normalization and correlation requirements."
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ConnectedAppContactCreate"
      responses:
        "200":
          description: "Successful result"
          content:
            application/json:
              schema:
                type: "object"
                additionalProperties: false
                properties:
                  data:
                    $ref: "#/components/schemas/ConnectedAppContactReceipt"
                required:
                  - "data"
        "400":
          $ref: "#/components/responses/ValidationError"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          description: "Missing permission or wrong credential type"
        "404":
          description: "Contact or call unavailable; includes deleted, ambiguous and inaccessible records"
        "409":
          description: "Conflict or changed retry payload"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "429":
          description: "Rate limited; honor Retry-After"
        "500":
          description: "Failed operation; retry a write with its original key and payload"
      parameters:
        - name: "Idempotency-Key"
          in: "header"
          required: true
          schema:
            type: "string"
            pattern: "^[A-Za-z0-9._:-]{8,128}$"
  /api/v1/connected-apps/contacts/update:
    post:
      x-seedly-oauth-scope: "contacts:write"
      x-seedly-resource-restrictions: {"oauth":["location","no_consent_or_assignment"]}
      summary: "Update basic contact details"
      description: "Requires expectedUpdatedAt from the last lookup or write. A stale version or duplicate
        identity returns 409. No consent, ownership, custom fields or deletion changes. OAuth only;
        API keys are refused. Strict JSON body limit is 16 KiB. See the connected-apps contract for
        replay, normalization and correlation requirements."
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ConnectedAppContactUpdate"
      responses:
        "200":
          description: "Successful result"
          content:
            application/json:
              schema:
                type: "object"
                additionalProperties: false
                properties:
                  data:
                    $ref: "#/components/schemas/ConnectedAppContactReceipt"
                required:
                  - "data"
        "400":
          $ref: "#/components/responses/ValidationError"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          description: "Missing permission or wrong credential type"
        "404":
          description: "Contact or call unavailable; includes deleted, ambiguous and inaccessible records"
        "409":
          description: "Conflict or changed retry payload"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "429":
          description: "Rate limited; honor Retry-After"
        "500":
          description: "Failed operation; retry a write with its original key and payload"
      parameters:
        - name: "Idempotency-Key"
          in: "header"
          required: true
          schema:
            type: "string"
            pattern: "^[A-Za-z0-9._:-]{8,128}$"
  /api/v1/connected-apps/calls/report:
    post:
      x-seedly-oauth-scope: "calls:write"
      x-seedly-resource-restrictions: {"oauth":["integration_owned"]}
      summary: "Report a completed call"
      description: "Final immutable report. Reuse the original retry key and external call ID. Optional
        crmCallLogId must match location, contact and direction; it appends notes without replacing
        carrier facts or creating a second call. Without it a new call is created. At most one report
        per app and CRM call. Future end time beyond five minutes or elapsed time over 24 hours is
        refused. No billing, media ingestion, transfer commands or outbound call initiation. OAuth
        only; API keys are refused. Strict JSON body limit is 16 KiB. See the connected-apps contract
        for replay, normalization and correlation requirements."
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ConnectedAppCallReport"
      responses:
        "200":
          description: "Successful result"
          content:
            application/json:
              schema:
                type: "object"
                additionalProperties: false
                properties:
                  data:
                    $ref: "#/components/schemas/ConnectedAppCallReceipt"
                required:
                  - "data"
        "400":
          $ref: "#/components/responses/ValidationError"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          description: "Missing permission or wrong credential type"
        "404":
          description: "Contact or call unavailable; includes deleted, ambiguous and inaccessible records"
        "409":
          description: "Conflict or changed retry payload"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "429":
          description: "Rate limited; honor Retry-After"
        "500":
          description: "Failed operation; retry a write with its original key and payload"
      parameters:
        - name: "Idempotency-Key"
          in: "header"
          required: true
          schema:
            type: "string"
            pattern: "^[A-Za-z0-9._:-]{8,128}$"
  # =========================================================================
  # CONTACTS
  # =========================================================================
  /api/v1/contacts:
    get:
      x-seedly-oauth-scope: "contacts:read"
      x-seedly-standard-scope: "contacts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listContacts
      tags: [Contacts]
      summary: List contacts
      description: |
        List, search, and filter contacts. Supports cursor-based pagination.
        Pass `email` for exact email lookup (returns 0 or 1 result).
        Pass `search` for free-text search.

        `meta.total` is a bounded count. For Standard v2 and OAuth,
        `meta.totalIsLowerBound` is true when it is a floor and false when it is exact.

        Search has no cursor. For Standard v2 and OAuth, each of the three search
        indexes reads at most 256 rows or 3 MiB, `meta.total` counts the matches read,
        and `meta.truncated` is always present on a search. It is true, with `hasMore`
        true and `cursor` null, when a read cap or `limit` stopped the answer. Narrow the
        search or filters to see the rest. Legacy keys keep their response, with neither field.
      parameters:
        - name: email
          in: query
          description: Exact email lookup (mutually exclusive with `search`)
          schema:
            type: string
            format: email
        - name: search
          in: query
          description: Free-text search across name, email, phone, company
          schema:
            type: string
        - name: lifecycleStage
          in: query
          schema:
            $ref: "#/components/schemas/LifecycleStage"
        - name: source
          in: query
          description: Filter by creation source
          schema:
            type: string
        - name: tags
          in: query
          description: Comma-separated tag names
          schema:
            type: string
        - name: assignedTo
          in: query
          description: Filter by assignee user ID
          schema:
            type: string
        - name: hasPhone
          in: query
          description: Filter contacts that have a phone number
          schema:
            type: string
            enum: ["true", "false"]
        - name: limit
          in: query
          description: Results per page (default 50, max 100)
          schema:
            type: integer
            minimum: 1
            maximum: 100
        - name: cursor
          in: query
          description: Pagination cursor from previous response
          schema:
            type: string
      responses:
        "200":
          description: List of contacts
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
            X-RateLimit-Limit:
              $ref: "#/components/headers/X-RateLimit-Limit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/X-RateLimit-Remaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/X-RateLimit-Reset"
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Contact"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
              example:
                data:
                  - id: "j975e4n5dqv5gq0r3bgd"
                    agencyId: "a123abc"
                    subAccountId: "s456def"
                    firstName: "Jane"
                    lastName: "Doe"
                    email: "jane@example.com"
                    phone: "+15551234567"
                    company: "Acme Corp"
                    lifecycleStage: "lead"
                    tags: ["website-lead"]
                    customFields: {}
                    additionalEmails: []
                    additionalPhones: []
                    isActive: true
                    createdAt: "2026-03-27T14:30:00.000Z"
                    updatedAt: "2026-03-27T14:30:00.000Z"
                meta:
                  total: 142
                  hasMore: true
                  cursor: "eyJwb3..."
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/RateLimited"

    post:
      x-seedly-oauth-scope: "contacts:write"
      x-seedly-standard-scope: "contacts:write"
      x-seedly-resource-restrictions: {"oauth":["location","no_consent_or_assignment"],"standard":["location"]}
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          description: Required for OAuth writes. Existing API-key requests retain their
            original behavior.
          schema:
            type: string
            minLength: 8
            maxLength: 128
            pattern: ^[A-Za-z0-9._:-]+$
      x-seedly-oauth-write-contract: OAuth requires Idempotency-Key (8-128 ASCII letters, digits, dot, underscore, colon or hyphen). Returns a minimal receipt; read permission is required to fetch records. API-key behavior is unchanged.
      operationId: createContact
      tags: [Contacts]
      summary: Create a contact (email-idempotent)
      description: |
        Create a new contact. `firstName` and `lastName` are required.
        The contact `source` defaults to `"api"` when created via the API.

        When `email` is provided and a contact with the same (normalized)
        email already exists in the sub-account, the request MERGES into
        the existing contact instead of creating a duplicate: tags are
        unioned, empty fields are filled (non-empty existing values are
        never overwritten), `lifecycleStage` only moves forward, and
        `customFields` shallow-merge with incoming keys winning. The
        response then carries `merged: true` and no `contact.created`
        webhook fires (newly-added tags still fire `contact.tag_added`;
        a lifecycle advance fires `contact.lifecycle_changed`). Merging
        into a previously deleted contact revives it with full restore
        semantics and DOES fire `contact.created`.
        Requests without an `email` always create a new contact.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ContactCreate"
            example:
              firstName: "Jane"
              lastName: "Doe"
              email: "jane@example.com"
              phone: "+15551234567"
              company: "Acme Corp"
              lifecycleStage: "lead"
              tags: ["website-lead"]
      responses:
        "201":
          description: Contact created (or merged into an existing contact with the same email)
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                anyOf:
                  - type: object
                    required:
                      - data
                    properties:
                      data:
                        allOf:
                          - $ref: "#/components/schemas/Contact"
                          - type: object
                            properties:
                              merged:
                                type: boolean
                                description: true when the request merged into an existing contact with the same
                                  email instead of creating a new one.
                  - $ref: "#/components/schemas/OAuthWriteResponse"
        "400":
          $ref: "#/components/responses/ValidationError"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/RateLimited"

  /api/v1/contacts/fields:
    get:
      x-seedly-oauth-scope: "contacts:read"
      x-seedly-standard-scope: "contacts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listContactFields
      tags: [Contacts]
      summary: List custom field definitions
      description: Returns all custom field definitions for the sub-account.
      responses:
        "200":
          description: List of custom field definitions
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/CustomFieldDefinition"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"

  /api/v1/contacts/{id}:
    parameters:
      - name: id
        in: path
        required: true
        description: Contact ID
        schema:
          type: string
    get:
      x-seedly-oauth-scope: "contacts:read"
      x-seedly-standard-scope: "contacts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getContact
      tags: [Contacts]
      summary: Get a contact
      responses:
        "200":
          description: Contact details
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    $ref: "#/components/schemas/Contact"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"

    patch:
      x-seedly-oauth-scope: "contacts:write"
      x-seedly-standard-scope: "contacts:write"
      x-seedly-record-grant-approvals: {"minPolicyVersion":5,"options":["allowReassign"],"nullRemovalPolicyVersion":7,"nullRemovalFields":["assignedTo"]}
      x-seedly-resource-restrictions: {"oauth":["location","no_consent_or_assignment"],"standard":["location"]}
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          description: Required for OAuth writes. Existing API-key requests retain their
            original behavior.
          schema:
            type: string
            minLength: 8
            maxLength: 128
            pattern: ^[A-Za-z0-9._:-]+$
      x-seedly-oauth-write-contract: OAuth requires Idempotency-Key (8-128 ASCII letters, digits, dot, underscore, colon or hyphen). Returns a minimal receipt; read permission is required to fetch records. API-key behavior is unchanged.
      operationId: updateContact
      tags: [Contacts]
      summary: Update a contact
      description: |
        Partial update. Only include fields you want to change.
        Read-only fields (`engagementScore`, `source`, `createdAt`, `updatedAt`, `isActive`) are silently ignored.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ContactUpdate"
      responses:
        "200":
          description: Updated contact
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                anyOf:
                  - type: object
                    required:
                      - data
                    properties:
                      data:
                        $ref: "#/components/schemas/Contact"
                  - $ref: "#/components/schemas/OAuthWriteResponse"
        "400":
          $ref: "#/components/responses/ValidationError"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

    put:
      x-seedly-oauth-scope: "contacts:write"
      x-seedly-standard-scope: "contacts:write"
      x-seedly-resource-restrictions: {"oauth":["location","no_consent_or_assignment"],"standard":["location"]}
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          description: Required for OAuth writes. Existing API-key requests retain their
            original behavior.
          schema:
            type: string
            minLength: 8
            maxLength: 128
            pattern: ^[A-Za-z0-9._:-]+$
      x-seedly-oauth-write-contract: OAuth requires Idempotency-Key (8-128 ASCII letters, digits, dot, underscore, colon or hyphen). Returns a minimal receipt; read permission is required to fetch records. API-key behavior is unchanged.
      operationId: updateContactPut
      tags: [Contacts]
      summary: Update a contact (PUT alias)
      description: |
        Alias of `PATCH /api/v1/contacts/{id}` for HTTP tooling that only
        offers the classic verb set (e.g. chatbot custom-tool builders).
        Identical partial-update semantics - this is NOT a full-document
        replace. Only include fields you want to change.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ContactUpdate"
      responses:
        "200":
          description: Updated contact
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                anyOf:
                  - type: object
                    required:
                      - data
                    properties:
                      data:
                        $ref: "#/components/schemas/Contact"
                  - $ref: "#/components/schemas/OAuthWriteResponse"
        "400":
          $ref: "#/components/responses/ValidationError"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

    delete:
      x-seedly-oauth-scope: "contacts:delete"
      x-seedly-standard-scope: "contacts:delete"
      x-seedly-resource-restrictions: {"oauth":["location","record_grant_required"],"standard":["location"]}
      operationId: deleteContact
      parameters:
        - in: header
          name: Idempotency-Key
          required: false
          schema: { type: string, minLength: 8, maxLength: 128 }
          description: Required for restricted Standard v2 and OAuth deletion. OAuth requires version 4 restricted record consent. Unsupported cleanup is refused before effects. Legacy and unrestricted Standard keys retain their existing behavior.
      tags: [Contacts]
      summary: Delete a contact
      responses:
        "200":
          description: Contact deleted
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: object
                    required: [id, deleted]
                    properties:
                      id:
                        type: string
                      deleted:
                        type: boolean
                        const: true
              example:
                data:
                  id: "j975e4n5dqv5gq0r3bgd"
                  deleted: true
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

  /api/v1/contacts/bot-update:
    put:
      operationId: botUpdateContactFromBody
      tags: [Contacts]
      summary: Update a contact using a flat body with a system-bound contact ID
      description: >-
        The CloseBot-compatible form of the scalar update endpoint. CloseBot's
        native Contact.ID value is reliable inside a JSON body, while that same
        value inside a custom-tool URL path currently resolves to the bare base
        URL at execution time. This route therefore takes `contactId` in the
        same flat body as the update instruction. The custom
        tool must bind `contactId` to the platform-owned Contact.ID variable,
        never expose it as an AI-supplied tool parameter. Authentication,
        authorization, validation, rate limiting, tenancy isolation, and update
        semantics are identical to `/api/v1/contacts/{id}/bot-update`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [contactId, operation]
              properties:
                contactId:
                  type: string
                  description: Contact ID injected by the bot platform from the active conversation.
                operation:
                  type: string
                  enum: [set_field, set_custom_field, add_tag, remove_tag]
                field:
                  type: string
                  description: Standard field name or exact custom-field key; unused by tag operations.
                value:
                  type: string
                  description: The value to write, or the single tag to add or remove.
            example:
              contactId: qx75stf76fk3gzkc4npdfaakan8e4qv4
              operation: set_field
              field: timezone
              value: America/New_York
      responses:
        "200":
          description: The updated contact
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Contact"
        "400":
          $ref: "#/components/responses/ValidationError"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"

  /api/v1/contacts/{id}/messaging-status:
    parameters:
      - name: id
        in: path
        required: true
        description: Contact ID
        schema:
          type: string
    get:
      operationId: getContactMessagingStatus
      tags: [Contacts]
      summary: Check whether a contact can be messaged
      description: |
        Whether this contact can be sent SMS and email right now, split into
        transactional (confirmations, reminders, receipts) and marketing
        (promotions, broadcasts). Each verdict applies the same checks the
        CRM's own senders apply, in the same order, and `reason` names the
        first one that blocks:

        - **SMS transactional**: phone on file (`no_phone`), do-not-disturb
          (`dnd`), STOP / SMS opt-out (`sms_opted_out`), SMS suppression list
          (`suppressed`).
        - **SMS marketing**: every SMS transactional check, then marketing SMS
          consent. Contacts added after marketing texts started requiring
          opt-in need recorded marketing consent
          (`marketing_sms_consent_required`); a contact who declined or
          revoked marketing texts is always blocked
          (`marketing_sms_consent_declined`).
        - **Email transactional**: email on file (`no_email`), hard
          suppression only (bounce, spam complaint, manual block:
          `suppressed`). A marketing unsubscribe never blocks transactional
          email.
        - **Email marketing**: email on file (`no_email`), do-not-disturb
          (`dnd`), email opt-out (`unsubscribed`), suppression list including
          unsubscribe-all (`suppressed`).

        An allowed verdict has `reason: allowed`. Opt-outs from an individual
        List are per List and are not reflected here. Requires `contacts:read`;
        the contact must belong to the API key's sub-account.
      responses:
        "200":
          description: Messaging status
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    $ref: "#/components/schemas/ContactMessagingStatus"
              example:
                data:
                  contactId: "j57a1b2c3d4e5f6g7h8i9j0k"
                  sms:
                    transactional: { allowed: true, reason: allowed }
                    marketing: { allowed: false, reason: marketing_sms_consent_required }
                  email:
                    transactional: { allowed: true, reason: allowed }
                    marketing: { allowed: true, reason: allowed }
        "400":
          $ref: "#/components/responses/ValidationError"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"

  /api/v1/contacts/{id}/bot-update:
    parameters:
      - name: id
        in: path
        required: true
        description: Contact ID
        schema:
          type: string
    put:
      operationId: botUpdateContact
      tags: [Contacts]
      summary: Update a contact using a flat, scalar-only body
      description: >-
        A companion to `PATCH`/`PUT /api/v1/contacts/{id}` for chatbot
        custom-tool builders that can only substitute SCALAR values into a
        request body and therefore cannot send a nested object. Such a builder
        rejects a template like `{"customFields": {{updates_json}}}` as invalid
        JSON and sends an empty update instead, which succeeds and writes
        nothing. This endpoint takes one instruction at a time and does the
        shaping server-side. Tag operations merge against the stored array, so
        the caller never constructs or preserves one, and `add_tag` is
        idempotent and case-insensitive. Same authentication, `contacts:write`
        scope, rate-limit bucket and sub-account isolation as the JSON
        endpoints.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [operation]
              properties:
                operation:
                  type: string
                  enum: [set_field, set_custom_field, add_tag, remove_tag]
                  description: >-
                    `set_field` sets one allowlisted standard column;
                    `set_custom_field` sets one custom-field key;
                    `add_tag` / `remove_tag` merge one tag.
                field:
                  type: string
                  description: >-
                    For `set_field`, one of firstName, lastName, email, phone,
                    company, title, lifecycleStage, addressLine1, addressLine2,
                    city, state, postalCode, country, dateOfBirth, timezone.
                    For `set_custom_field`, the exact custom-field key. Unused
                    by the tag operations. Anything else is a 400; `source` and
                    `assignedTo` are deliberately not settable by a bot.
                value:
                  type: string
                  description: >-
                    The new value, or the tag for `add_tag` / `remove_tag`. An
                    empty string clears a field or custom field.
            example:
              operation: add_tag
              value: vip
      responses:
        "200":
          description: The updated contact
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Contact"
        "400":
          $ref: "#/components/responses/ValidationError"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"


  # =========================================================================
  # CONVERSATIONS
  # =========================================================================
  /api/v1/conversations:
    get:
      x-seedly-oauth-scope: "conversations:read"
      x-seedly-standard-scope: "conversations:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listConversations
      tags: [Conversations]
      summary: List conversations
      description: >-
        Standard v2 and OAuth: cursor pages, newest activity first, where a thread with no messages
        ranks by its creation time. Every filter applies. A scan stops at 2000 rows or 8 MiB, so a page
        can be short or empty while meta.hasMore is true; stop only when meta.hasMore is false. A cursor
        is bound to the credential, location and filters; any other use is a 400. A walk is not a
        snapshot, so a thread that gets a new message before it is returned can be skipped and one whose
        activity moves backward can repeat. Legacy keys keep their original bounded scan, which ignores
        status when contactId is set, has no meta and ignores cursor.
      parameters:
        - name: contactId
          in: query
          description: Filter by contact ID
          schema:
            type: string
        - name: status
          in: query
          schema:
            $ref: "#/components/schemas/ConversationStatus"
        - name: channel
          in: query
          schema:
            $ref: "#/components/schemas/Channel"
        - name: assignedTo
          in: query
          description: Filter by assignee user ID
          schema:
            type: string
        - name: limit
          in: query
          description: Results per page (default 50, max 100)
          schema:
            type: integer
            minimum: 1
            maximum: 100
        - name: cursor
          in: query
          description: Standard v2 and OAuth only. Pass meta.cursor from the previous page unchanged, with the same filters.
          schema:
            type: string
            maxLength: 8192
      responses:
        "200":
          description: List of conversations
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Conversation"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
        "400":
          description: Invalid limit or cursor (Standard v2 and OAuth)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"

    post:
      x-seedly-oauth-scope: "conversations:write"
      x-seedly-standard-scope: "conversations:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          description: Required for OAuth writes. Existing API-key requests retain their
            original behavior.
          schema:
            type: string
            minLength: 8
            maxLength: 128
            pattern: ^[A-Za-z0-9._:-]+$
      x-seedly-oauth-write-contract: OAuth requires Idempotency-Key (8-128 ASCII letters, digits, dot, underscore, colon or hyphen). Returns a minimal receipt; read permission is required to fetch records. API-key behavior is unchanged.
      operationId: createConversation
      tags: [Conversations]
      summary: Create or find a conversation
      description: |
        Creates a new conversation for the given contact and channel. If an open conversation
        already exists for that contact/channel pair, returns the existing conversation instead.
        Check the `created` field in the response to distinguish.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ConversationCreate"
            example:
              contactId: "j975e4n5dqv5gq0r3bgd"
              channel: "sms"
      responses:
        "200":
          description: Existing conversation returned
          content:
            application/json:
              schema:
                anyOf:
                  - type: object
                    required:
                      - data
                    properties:
                      data:
                        $ref: "#/components/schemas/ConversationWithCreatedFlag"
                  - $ref: "#/components/schemas/OAuthWriteResponse"
        "201":
          description: New conversation created
          content:
            application/json:
              schema:
                anyOf:
                  - type: object
                    required:
                      - data
                    properties:
                      data:
                        $ref: "#/components/schemas/ConversationWithCreatedFlag"
                  - $ref: "#/components/schemas/OAuthWriteResponse"
        "400":
          $ref: "#/components/responses/ValidationError"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"

  /api/v1/conversations/{id}:
    parameters:
      - name: id
        in: path
        required: true
        description: Conversation ID
        schema:
          type: string
    get:
      x-seedly-oauth-scope: "conversations:read"
      x-seedly-standard-scope: "conversations:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getConversation
      tags: [Conversations]
      summary: Get a conversation
      responses:
        "200":
          description: Conversation details
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    $ref: "#/components/schemas/Conversation"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

    patch:
      x-seedly-oauth-scope: "conversations:write"
      x-seedly-standard-scope: "conversations:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          description: Required for OAuth writes. Existing API-key requests retain their
            original behavior.
          schema:
            type: string
            minLength: 8
            maxLength: 128
            pattern: ^[A-Za-z0-9._:-]+$
      x-seedly-oauth-write-contract: OAuth requires Idempotency-Key (8-128 ASCII letters, digits, dot, underscore, colon or hyphen). Returns a minimal receipt; read permission is required to fetch records. API-key behavior is unchanged.
      operationId: updateConversation
      tags: [Conversations]
      summary: Update a conversation
      description: Update the status or assignee of a conversation.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ConversationUpdate"
            example:
              status: "closed"
      responses:
        "200":
          description: Conversation updated
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                anyOf:
                  - type: object
                    required:
                      - data
                    properties:
                      data:
                        type: object
                        required:
                          - id
                          - updated
                        properties:
                          id:
                            type: string
                          updated:
                            type: boolean
                            const: true
                  - $ref: "#/components/schemas/OAuthWriteResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

  /api/v1/conversations/{id}/messages:
    parameters:
      - name: id
        in: path
        required: true
        description: |
          Conversation ID. For POST, a contact ID is also accepted (additive,
          for template-driven integrators that only know the contact): the
          message is delivered to that contact's most recently active
          conversation, preferring one matching the `channel` body field when
          given. If the selected conversation has been taken over by a human
          (bot replies paused), the request returns 404.
        schema:
          type: string
    get:
      x-seedly-oauth-scope: "conversations:read"
      x-seedly-standard-scope: "conversations:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listMessages
      tags: [Conversations]
      summary: List messages in a conversation
      description: Returns messages in reverse chronological order (newest first). Supports cursor-based pagination.
      parameters:
        - name: limit
          in: query
          description: Results per page (default 50, max 100)
          schema:
            type: integer
            minimum: 1
            maximum: 100
        - name: cursor
          in: query
          description: Pagination cursor from previous response
          schema:
            type: string
      responses:
        "200":
          description: List of messages
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Message"
                  meta:
                    type: object
                    properties:
                      hasMore:
                        type: boolean
                      cursor:
                        type:
                          - string
                          - "null"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"

    post:
      x-seedly-oauth-scope: "messages:send"
      x-seedly-standard-scope: "messages:send"
      x-seedly-resource-restrictions: {"oauth":["configured_sender","contact_recipient"],"standard":["location"]}
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          description: Required for OAuth writes. Existing API-key requests retain their
            original behavior.
          schema:
            type: string
            minLength: 8
            maxLength: 128
            pattern: ^[A-Za-z0-9._:-]+$
      x-seedly-oauth-write-contract: OAuth requires Idempotency-Key (8-128 ASCII letters, digits, dot, underscore, colon or hyphen). Returns a minimal receipt; read permission is required to fetch records. API-key behavior is unchanged.
      operationId: sendMessage
      tags: [Conversations]
      summary: Send a message
      description: |
        Send a message in an existing conversation. `bodyText` is required.
        `channel` is optional since 5.8.0: when absent (or an empty /
        unsubstituted `{{...}}` template value), the message is delivered on
        the target conversation's own channel. When `toAddress` is omitted it
        falls back to the contact's phone (sms) or email (email channels).
        For email, also provide `subject` and optionally `bodyHtml`.
        If the API key is a test mode key (`sk_test_*`), the message is recorded but not delivered to the provider.
        `fileIds` attaches up to 20 attachment files on an email thread. It needs a location-wide
        Standard v2 key or OAuth grant that also holds files:read, cannot be combined with
        `toAddress`, and requires Idempotency-Key. Legacy API keys are refused when they send it.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SendMessage"
            example:
              bodyText: "Hi Jane, your appointment is confirmed for tomorrow at 2pm."
              channel: "sms"
      responses:
        "201":
          description: Message sent
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                anyOf:
                  - type: object
                    required:
                      - data
                    properties:
                      data:
                        $ref: "#/components/schemas/Message"
                  - $ref: "#/components/schemas/OAuthWriteResponse"
        "400":
          $ref: "#/components/responses/ValidationError"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

  # =========================================================================
  # CALENDARS
  # =========================================================================
  /api/v1/calendars:
    get:
      x-seedly-standard-scope: "calendars:read"
      x-seedly-resource-restrictions: {"standard":["published_catalog"]}
      operationId: listCalendars
      tags: [Calendars]
      summary: List calendars
      description: |
        Returns all active calendars for the sub-account.

        Requires the `availability:read` scope. **This changed in 5.8.0.** It
        used to require `calendars:read`, which also opened
        `GET /api/v1/calendars/appointments` and the customer details on it.
        The list carries no customer data of its own, so a booking integration
        no longer has to hold the appointment roster just to discover which
        calendars exist. A key holding only `appointments:read` now gets
        `403 FORBIDDEN` here.
      responses:
        "200":
          description: List of calendars
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Calendar"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"

    post:
      x-seedly-oauth-scope: "calendars:write"
      x-seedly-standard-scope: "calendars:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createIntegrationCalendar
      summary: "create Integration Calendar"
      tags: [Integrations]
      description: "Create a personal calendar using native calendar business rules. Requires calendars:write, calendar plan feature and a reachable active author. Slug must be unique. Stable Idempotency-Key required. Maximum body 256 KiB."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Authorized projection or idempotent write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","created"],"properties":{"id":{"type":"string"},"created":{"const":true}}}}}}}},"400":{"description":"Invalid request."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked or stale operation approval."},"404":{"description":"Record or parent unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Idempotency key reused for another request."},"413":{"description":"Request body too large."},"415":{"description":"JSON content type required."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":255},"slug":{"type":"string","minLength":1,"maxLength":100},"timezone":{"type":"string","maxLength":100},"description":{"type":"string","maxLength":5000}},"required":["name","slug","timezone"]}}}}
  /api/v1/calendars/types:
    get:
      x-seedly-oauth-scope: "calendars:read"
      x-seedly-standard-scope: "calendars:read"
      x-seedly-resource-restrictions: {"oauth":["published_catalog"],"standard":["published_catalog"]}
      operationId: listAppointmentTypes
      tags: [Calendars]
      summary: List appointment types
      description: |
        Returns active appointment types. Optionally filter by calendar.

        Requires the `availability:read` scope. **This changed in
        5.8.0.** It used to require `calendars:read`, which also opened
        `GET /api/v1/calendars/appointments` and the customer details on it. A
        key holding just `appointments:read` now gets `403 FORBIDDEN` here.
      parameters:
        - name: calendarId
          in: query
          description: Filter by calendar ID
          schema:
            type: string
      responses:
        "200":
          description: List of appointment types
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/AppointmentType"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"

  /api/v1/calendars/availability:
    get:
      x-seedly-oauth-scope: "calendars:read"
      x-seedly-standard-scope: "calendars:read"
      x-seedly-resource-restrictions: {"oauth":["published_catalog"],"standard":["published_catalog"]}
      operationId: getAvailability
      tags: [Calendars]
      summary: Get available time slots
      description: |
        Returns bookable slots for an appointment type, for one day or for a
        date range of up to 31 days.

        **Only bookable slots are returned.** A time that is already taken, is
        blocked, falls outside the calendar's hours or is inside the minimum
        notice window is left out of `data` entirely - it is never returned with
        `available: false`. `available` is present on every slot and is always
        `true`, and `meta.returnsOnlyAvailableSlots` says so on the wire.

        **An empty `data` array is not always "nothing free".** It is also the
        answer when nothing resolved - an unknown, inactive, archived or
        out-of-scope `appointmentTypeId`, or a deactivated sub-account. Check
        `meta.appointmentTypeId`: it is `null` in that case and set otherwise.

        Name the appointment type with EITHER `appointmentTypeId` OR
        `appointmentType` (its name or slug), never both. If a name or slug
        matches more than one BOOKABLE active appointment type, the request is
        refused with `400 VALIDATION_ERROR` and `error.details.matches` lists
        the candidates with their IDs, rather than one of them being picked. A
        type whose calendar is archived, or which belongs to another
        sub-account, is not a candidate and does not make a name ambiguous.

        Every slot carries the calendar's IANA timezone, its local date and a
        preformatted `label` rendered in that timezone, so a caller never has to
        turn a Unix timestamp into a day and time itself. Every slot's `date`
        falls inside `meta.startDate`..`meta.endDate`.

        **Cost.** A range costs one rate-limit slot PER DAY, not per request,
        because each day is a separate availability computation. A 31-day
        question spends 31 of the key's read allowance (120/min on a live key,
        30/min on a `sk_test_` key). A range wider than the key's whole
        allowance can never be served, so it is refused with
        `400 VALIDATION_ERROR` naming the maximum that key can ask for - never a
        `429` a retry could not fix. On a test key that ceiling is 30 days.

        On a `429`, `X-RateLimit-Remaining` is the budget genuinely left, which
        for a per-day charge is often more than zero; a shorter range will
        usually answer at once.

        If the range produces more slots than one response carries, it is cut
        off after whole days and `meta.truncated` is `true` - see
        `meta.daysReturned`.

        **Every slot returned here can be booked.** This endpoint applies the
        same rules the booking endpoint enforces, from the same code: the global
        horizon, and the business's own `minNotice` and `maxAdvance` as
        configured on the appointment type or the calendar. A time that is
        offered is a time that can be taken.

        Two consequences worth knowing before you cache anything:

        - **The answer is measured from now, not from midnight.** A business
          that takes bookings seven days ahead has its seventh day open only up
          to the current time of day, so asking again later opens a little more
          of it. Ask for availability when you need it rather than reusing an
          answer from earlier in the conversation.
        - **A slot can still be taken by somebody else between the two calls.**
          That is a lost race, not a mistake in your request, and the booking
          endpoint reports it as `error.details.reason: "slot_unavailable"` so
          you can offer another time instead of retrying.

        Requires the `availability:read` scope. **This changed in
        5.8.0.** It used to require `calendars:read`, which also opened
        `GET /api/v1/calendars/appointments` and the customer details on it, so
        a key issued only to answer "when are you free?" was carrying the
        location's booked-appointment list as well. A key holding just
        `appointments:read` now gets `403 FORBIDDEN` here.
      parameters:
        - name: appointmentTypeId
          in: query
          required: false
          description: |
            Appointment type ID. Required unless `appointmentType` is given.
            An unknown, inactive or out-of-scope ID returns an empty `data`
            array with `200` and `meta.appointmentTypeId: null`.

            **It must be the `id` from `GET /api/v1/calendars/types`, not the
            `calendarId` beside it.** Every row of that response carries both,
            so this is the easiest field on the endpoint to get wrong. A valid
            ID for a different table is a `400 VALIDATION_ERROR` - a request to
            fix, not a server fault to retry. It used to answer `500`.
          schema:
            type: string
        - name: appointmentType
          in: query
          required: false
          description: |
            Appointment type name or slug (case-insensitive), as an alternative
            to `appointmentTypeId`. Returns `404 NOT_FOUND` when nothing matches
            and `400 VALIDATION_ERROR` when more than one bookable active type
            does. Maximum 200 characters.
          schema:
            type: string
            maxLength: 200
          example: "Roof Inspection"
        - name: date
          in: query
          required: true
          description: |
            Date to check (ISO 8601 date, e.g. `2026-04-01`). With no `endDate`
            this is the only day returned. Must be a real calendar date
            (`2026-02-31` is refused), written with two-digit month and day
            (`2026-4-1` is refused), and within 366 days before / 3660 days
            after today.
          schema:
            type: string
            format: date
        - name: endDate
          in: query
          required: false
          description: |
            Last day of the range, inclusive (ISO 8601 date). Must be on or
            after `date`, the range must span 31 days or fewer (30 on a
            `sk_test_` key - see Cost above), and it must end no more than 3660
            days after today.
          schema:
            type: string
            format: date
        - name: partOfDay
          in: query
          required: false
          description: |
            Return only openings in one part of the day: `morning` (before
            noon), `afternoon` (noon to 5pm) or `evening` (5pm onward).
            Measured on `customerTimezone` when that is supplied, otherwise on
            the calendar's timezone. Omit it for the whole day.

            Prefer this over filtering the full day yourself. An assistant told
            to exclude morning times still offered them; the endpoint does not.
          schema:
            type: string
            enum: [morning, afternoon, evening]
        - name: customerTimezone
          in: query
          required: false
          description: |
            The customer's IANA timezone. Decides which hours `partOfDay` means,
            and adds `customerLabel` to every slot so nothing has to convert
            between the calendar's clock and the customer's.
          schema:
            type: string
          example: "America/Los_Angeles"
      responses:
        "200":
          description: Available time slots
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/AvailabilitySlot"
                  meta:
                    $ref: "#/components/schemas/AvailabilityMeta"
              example:
                data:
                  # startTime/endTime are the SAME instants as start/end. They
                  # were 1774011600000 / 1774013400000 here, which is
                  # 2026-03-20 - twelve days before the ISO strings beside
                  # them, and 30 minutes apart, so the pair looked right. These
                  # are the numbers `POST /calendars/appointments` is handed
                  # back, so a reader copying the example booked the wrong day.
                  - start: "2026-04-01T13:00:00.000Z"
                    end: "2026-04-01T13:30:00.000Z"
                    startTime: 1775048400000
                    endTime: 1775050200000
                    date: "2026-04-01"
                    label: "Wednesday, April 1, 2026 at 9:00 AM EDT"
                    timezone: "America/New_York"
                    available: true
                meta:
                  timezone: "America/New_York"
                  appointmentTypeId: "k186f5n6eqw6hr1s4che"
                  appointmentTypeName: "Roof Inspection"
                  appointmentTypeSlug: "roof-inspection"
                  startDate: "2026-04-01"
                  endDate: "2026-04-01"
                  days: 1
                  daysReturned: 1
                  truncated: false
                  returnsOnlyAvailableSlots: true
        "400":
          $ref: "#/components/responses/ValidationError"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/RateLimited"

  /api/v1/calendars/appointments:
    get:
      x-seedly-standard-scope: "appointments:read"
      x-seedly-resource-restrictions: {"standard":["location"]}
      operationId: listAppointments
      tags: [Calendars]
      summary: List appointments
      description: |
        Returns booked appointments, each with the contact's first name, last
        name, email address and phone number where the appointment is linked to
        a contact. No date range is required, so an unfiltered call returns the
        most recent appointments for the sub-account.

        Requires the `appointments:read` scope, which since 5.8.0 no longer opens
        `/api/v1/calendars`, `/api/v1/calendars/availability` or
        `/api/v1/calendars/types`. Grant it only where the caller is meant to
        see customer details. A booking integration that answers "when are you
        free?" wants `availability:read` instead.

        Standard v2 pages with `meta.hasMore` and `meta.cursor`. The date range and
        status select rows, and a read stops after 2000 rows or 8 MiB, so a page can be
        short or empty while `hasMore` is true. A date range or `calendarId` reads in start
        time order, otherwise newest created first. A cursor continues only the
        credential, location and filters that produced it; any other is refused with 400.
        Legacy keys keep their bounded scan with no cursor and no `meta`.
      parameters:
        - name: calendarId
          in: query
          description: Filter by calendar ID
          schema:
            type: string
        - name: startDate
          in: query
          description: Filter appointments starting at or after this Unix timestamp (milliseconds)
          schema:
            type: integer
        - name: endDate
          in: query
          description: Filter appointments starting at or before this Unix timestamp (milliseconds)
          schema:
            type: integer
        - name: status
          in: query
          schema:
            $ref: "#/components/schemas/AppointmentStatus"
        - name: limit
          in: query
          description: Results per page (default 50, max 100)
          schema:
            type: integer
            minimum: 1
            maximum: 100
        - name: cursor
          in: query
          description: Standard v2 only. The meta.cursor of the previous page, with the same filters.
          schema:
            type: string
      responses:
        "200":
          description: List of appointments
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Appointment"
                  meta:
                    description: Standard v2 only. Absent for legacy keys.
                    type: object
                    properties:
                      hasMore: { type: boolean }
                      cursor: { type: ["string", "null"] }
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"

    post:
      x-seedly-oauth-scope: "appointments:write"
      x-seedly-standard-scope: "appointments:write"
      x-seedly-resource-restrictions: {"oauth":["bookable_slots"],"standard":["bookable_slots"]}
      operationId: bookAppointment
      tags: [Calendars]
      summary: Book an appointment
      description: |
        Books one of the slots `GET /api/v1/calendars/availability` returned.
        Send `startTime` and `endTime` exactly as that endpoint gave them.

        **OAuth connected apps:** requires `appointments:write` and a required
        `Idempotency-Key` header (8-128 safe characters). Only appointmentTypeId,
        startTime, endTime, firstName, lastName, email, optional phone, notes and
        confirmationMode are accepted (16 KiB maximum body). confirmationMode is
        `automatic` (default) or `requested`; requested skips the initial customer
        SMS only. Email, staff and reminder rules remain unchanged. Paid appointments,
        classes and custom booking forms must use the hosted page. OAuth success
        and identical retries return 200 with an OAuthBookingReceipt, not the legacy
        201 shape below. Reusing a key with different data returns 400.
        OAuth does not support the broad appointment-list/delete endpoints.

        The remainder describes the legacy API-key contract.
        **Every slot availability returns is bookable here.** Both endpoints
        apply the same limits from the same code: the global horizon, and the
        business's own `minNotice` and `maxAdvance`. A time you can read to a
        customer is a time you can take.

        They used not to. The global horizons disagreed by about eight years, so
        a slot three years out came back with a correct read-aloud label and
        then could not be booked; and `maxAdvance` was compared as a whole day
        when offering and as an instant when booking, so the last day of a
        business's window was advertised in full and refused in full. The
        `too_far_ahead` and `too_soon` reasons below now mean you asked without
        checking availability first, not that availability lied to you.

        **When a booking is refused, `error.details.reason` says why**, as a
        stable token you can branch on. Read that rather than the message, which
        is written for a person. The reasons:

        | `reason`           | What to do about it |
        | ------------------ | ------------------- |
        | `slot_unavailable` | Someone took that time first. Read availability again and offer another slot. **Do not retry the same request.** |
        | `invalid_duration` | The gap between `startTime` and `endTime` is not the appointment type's length. Send a slot's own pair. |
        | `outside_hours`    | Outside the calendar's opening hours for that day. |
        | `day_unavailable`  | The calendar does not open on that day of the week. |
        | `date_unavailable` | That specific date is blocked off. |
        | `day_full`         | The day has reached its per-day booking cap. |
        | `slot_in_past`     | That time has already started. |
        | `too_soon`         | Nearer than this business takes bookings for. |
        | `too_far_ahead`    | Further ahead than this business takes bookings for. |

        A `400` with no `details.reason` is an ordinary request-validation
        failure - a missing field, a malformed email, a value out of range.

        `details.field` names the request field to change.

        Requires the `appointments:write` scope, renamed from `calendars:write` in
        5.8.0 with no change to what it grants. A booking
        integration that both quotes availability and books needs
        `availability:read` for the first and `appointments:write` for the
        second.

        **Store the `id` from this response.** It is the only handle on the
        appointment a booking integration is guaranteed to keep. Reading the
        booking back from `GET /api/v1/calendars/appointments` needs
        `appointments:read`, which is the scope that also returns every customer's
        name, email address and phone number - so a key scoped only for booking
        deliberately cannot list its own appointments. Keep the `id` (and the
        `startTime`/`endTime` you sent) at your end rather than planning to look
        the booking up again. Cancelling later needs that `id` too:
        `DELETE /api/v1/calendars/appointments/{id}`.
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          description: Required for OAuth booking creation; optional for legacy API keys. Reuse only for an identical booking retry.
          schema:
            type: string
            pattern: '^[A-Za-z0-9._:-]{8,128}$'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              anyOf:
                - $ref: "#/components/schemas/BookAppointment"
                - $ref: "#/components/schemas/OAuthBookAppointment"
            example:
              appointmentTypeId: "k186f5n6eqw6hr1s4che"
              startTime: 1743508800000
              endTime: 1743510600000
              firstName: "Jane"
              lastName: "Doe"
              email: "jane@example.com"
      responses:
        '200':
          description: OAuth booking created or identical request replayed
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    $ref: '#/components/schemas/OAuthBookingReceipt'
        "201":
          description: Appointment booked
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    $ref: "#/components/schemas/Appointment"
        "400":
          description: Invalid request, or the booking was refused
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              examples:
                slot_taken:
                  summary: Someone booked that slot first
                  value:
                    error:
                      code: "VALIDATION_ERROR"
                      message: "That time is no longer free. Read the availability for this appointment type again and offer one of the times it returns."
                      details:
                        reason: "slot_unavailable"
                        field: "startTime"
                validation_error:
                  summary: An ordinary bad request
                  value:
                    error:
                      code: "VALIDATION_ERROR"
                      message: "appointmentTypeId, startTime, endTime, firstName, lastName, and email are required"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"

  /api/v1/calendars/appointments/{id}:
    parameters:
      - name: id
        in: path
        required: true
        description: Appointment ID
        schema:
          type: string
    delete:
      x-seedly-oauth-scope: "appointments:delete"
      x-seedly-standard-scope: "appointments:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: cancelAppointment
      tags: [Calendars]
      summary: Cancel an appointment
      description: |
        OAuth connections need `appointments:delete` and a stable `Idempotency-Key`, a
        replay returns the original receipt, and only an upcoming scheduled or confirmed
        appointment can be cancelled. OAuth cancellation is refused once the appointment
        has started; Standard API keys keep this route's existing behavior. Standard API keys keep this route's
        existing behavior.

        A Standard API key on this route does not remove the Zoom meeting or the Outlook
        event, and can cancel a past appointment. To remove them, cancel through
        `POST /api/v1/appointments/{id}/series/cancel` with `scope: this`, which needs
        `appointments:delete`, or through an OAuth connection on this route.

        Cancels an appointment by ID within the authenticated sub-account. An
        ID belonging to another sub-account is reported as `404 NOT_FOUND`.

        Requires the `appointments:delete` capability for Standard keys, whose legacy check is the `appointments:write` scope that
        books an appointment. Renamed from `calendars:write` in 5.8.0 with no
        change to what it grants.
      parameters:
        - name: reason
          in: query
          description: Optional cancellation reason
          schema:
            type: string
      responses:
        "200":
          description: Appointment cancelled
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: object
                    required: [id, cancelled]
                    properties:
                      id:
                        type: string
                      cancelled:
                        type: boolean
                        const: true
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

  # =========================================================================
  # WEBHOOKS
  # =========================================================================
    get:
      x-seedly-oauth-scope: "appointments:read"
      x-seedly-standard-scope: "appointments:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getIntegrationAppointment
      summary: "get Integration Appointment"
      tags: [Integrations]
      description: "Requires location-wide appointments:read and contacts:read with fresh operation approval. Returns safe roster fields; provider IDs, booking tokens and nested contact details are omitted."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Authorized projection or idempotent write receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","calendarId","appointmentTypeId","contactId","title","startTime","endTime","status","assignedTo"],"properties":{"id":{"type":"string"},"calendarId":{"type":"string"},"appointmentTypeId":{"type":["string","null"]},"contactId":{"type":["string","null"]},"title":{"type":["string","null"]},"startTime":{"type":"string"},"endTime":{"type":"string"},"status":{"type":"string"},"assignedTo":{"type":["string","null"]}}}}}}}},"400":{"description":"Invalid request."},"401":{"description":"Invalid credential."},"403":{"description":"Missing, revoked or stale operation approval."},"404":{"description":"Record or parent unavailable."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/reviews:
    get:
      x-seedly-oauth-scope: "reviews:read"
      x-seedly-standard-scope: "reviews:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReviews
      tags: [Reputation]
      summary: List reviews
      description: "Standard v2 or OAuth only; legacy keys are denied. Existing Standard keys need explicit approval of this route. Record-restricted grants are denied."
      parameters: [{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/reviews/stats:
    get:
      x-seedly-oauth-scope: "reviews:read"
      x-seedly-standard-scope: "reviews:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReviewsStats
      tags: [Reputation]
      summary: Read review statistics
      description: "Standard v2 or OAuth only; legacy keys are denied. Existing Standard keys need explicit approval of this route. Record-restricted grants are denied. capped is true when the read stopped at its row or size limit; totals are then a floor over the newest records read."
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/reviews/platform-stats:
    get:
      x-seedly-oauth-scope: "reviews:read"
      x-seedly-standard-scope: "reviews:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReviewsPlatformStats
      tags: [Reputation]
      summary: Read review statistics by platform
      description: "Standard v2 or OAuth only; legacy keys are denied. Existing Standard keys need explicit approval of this route. Record-restricted grants are denied. capped is true when the read stopped at its row or size limit; totals are then a floor over the newest records read."
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/reviews/{id}:
    get:
      x-seedly-oauth-scope: "reviews:read"
      x-seedly-standard-scope: "reviews:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReviewsById
      tags: [Reputation]
      summary: Read a review
      description: "Standard v2 or OAuth only; legacy keys are denied. Existing Standard keys need explicit approval of this route. Record-restricted grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/review-requests:
    get:
      x-seedly-oauth-scope: "reviews:read"
      x-seedly-standard-scope: "reviews:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReviewRequests
      tags: [Reputation]
      summary: List review requests
      description: "Standard v2 or OAuth only; legacy keys are denied. Existing Standard keys need explicit approval of this route. Record-restricted grants are denied."
      parameters: [{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "review-requests:send"
      x-seedly-standard-scope: "review-requests:send"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: postReviewRequests
      tags: [Reputation]
      summary: Send a review request
      description: "Standard v2 or OAuth only; legacy keys are denied. Existing Standard keys need explicit approval of this route. Record-restricted grants are denied. Sends the location template to one contact through the configured sender. A contact can be asked once in 7 days. Returns 409 and records nothing when the contact has no address for the channel or has refused it. For SMS and email, the receipt starts as queued, changes to sent only after provider acceptance, and becomes failed if delivery is blocked. The queued message, and any later reminder, rechecks the app's live send and contact-read permission immediately before each provider attempt; a refused reminder is not sent and is not recorded as sent. Bulk review requests are started by signed-in staff and have no API route. Also requires contacts:read approval."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"contactId":{"type":"string"},"channel":{"type":"string","enum":["sms","email"]},"platform":{"type":"string","maxLength":50},"reviewLink":{"type":"string","maxLength":2048,"description":"Must match a configured review destination."}}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/review-requests/stats:
    get:
      x-seedly-oauth-scope: "reviews:read"
      x-seedly-standard-scope: "reviews:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReviewRequestsStats
      tags: [Reputation]
      summary: Read review request statistics
      description: "Standard v2 or OAuth only; legacy keys are denied. Existing Standard keys need explicit approval of this route. Record-restricted grants are denied. capped is true when the read stopped at its row or size limit; totals are then a floor over the newest records read."
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/reviews/{id}/flag:
    post:
      x-seedly-oauth-scope: "reviews:write"
      x-seedly-standard-scope: "reviews:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: postReviewsByIdFlag
      tags: [Reputation]
      summary: Flag a review
      description: "Standard v2 or OAuth only; legacy keys are denied. Existing Standard keys need explicit approval of this route. Record-restricted grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/reviews/{id}/reply:
    post:
      x-seedly-oauth-scope: "reviews:reply"
      x-seedly-standard-scope: "reviews:reply"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: postReviewsByIdReply
      tags: [Reputation]
      summary: Post a public review reply
      description: "Standard v2 or OAuth only; legacy keys are denied. Existing Standard keys need explicit approval of this route. Record-restricted grants are denied. The reply is stored and, when the connected platform allows it, posted publicly under the business name. Refused for test credentials."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"content":{"type":"string","maxLength":4096}}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/appointments:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsAppointments
      tags: [Reports]
      summary: Appointment report
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Each report also needs read approval for its record family. A report past an internal read limit still answers with top-level truncated true. Its figures are then partial and can be too high or too low, so do not use them as totals."
      parameters: [{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/invoices:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsInvoices
      tags: [Reports]
      summary: Invoice report
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Each report also needs read approval for its record family. This report needs both invoices:read and payments:read approval, because its revenue is dated by payment. revenueCollected is net cash in the window: invoice payments on the date each moved, with refunds as negative amounts, external payments, and any amount with no payment record on an invoice paid in the window, whenever that invoice was created. totalInvoices, outstandingAmount, overdueAmount, overdueCount, avgInvoiceValue and statusBreakdown cover invoices created in the window, and paidCount counts those that were also paid in it. Its figures are exact: when a payment or invoice read cannot finish, it answers 422 with no figures rather than a partial total, so truncated is false on every success. A shorter date range can help. Opportunity funnel revenue is a different figure, see that report."
      parameters: [{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/conversations:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsConversations
      tags: [Reports]
      summary: Conversation report
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Each report also needs read approval for its record family."
      parameters: [{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/pipelines:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsPipelines
      tags: [Reports]
      summary: Pipeline report
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Each report also needs read approval for its record family. A report past an internal read limit still answers with top-level truncated true. Its figures are then partial and can be too high or too low, so do not use them as totals."
      parameters: [{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}},{"name":"pipelineId","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/lifecycle:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsLifecycle
      tags: [Reports]
      summary: Customer lifecycle report
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Each report also needs read approval for its record family. Paid invoices count toward the Repeat stage only when the credential also holds invoices:read and payments:read approval, and OAuth counts only invoices the consenting user may view. Otherwise they are not read and paidInvoicesCounted is false. A report past an internal read limit still answers with top-level truncated true. Its figures are then partial and can be too high or too low, so do not use them as totals. capped carries the same value."
      parameters: [{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/win-loss:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsWinLoss
      tags: [Reports]
      summary: Win and loss report
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Each report also needs read approval for its record family. A report past an internal read limit still answers with top-level truncated true. Its figures are then partial and can be too high or too low, so do not use them as totals."
      parameters: [{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}},{"name":"pipelineId","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/sales-velocity:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsSalesVelocity
      tags: [Reports]
      summary: Sales velocity report
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Each report also needs read approval for its record family. A report past an internal read limit still answers with top-level truncated true. Its figures are then partial and can be too high or too low, so do not use them as totals."
      parameters: [{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}},{"name":"pipelineId","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/revenue-forecast:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsRevenueForecast
      tags: [Reports]
      summary: Revenue forecast report
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Each report also needs read approval for its record family. data stays an array. When a read limit cut the rows meta.truncated is true. They are then partial and can be too high or too low, so do not use them as totals."
      parameters: [{"name":"pipelineId","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"type":"object","required":["truncated"],"properties":{"truncated":{"type":"boolean"}}}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/dashboard-kpis:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsDashboardKpis
      tags: [Reports]
      summary: Dashboard KPIs
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. Needs contacts:read, conversations:read, appointments:read and opportunities:read. dateFrom is a whole UTC day within the last 366 days. Each capped field marks a count that stopped at its read limit, and truncated is true when any read stopped early."
      parameters: [{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/dashboard-summary:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsDashboardSummary
      tags: [Reports]
      summary: Dashboard summary
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Needs contacts, opportunities, conversations, appointments, invoices, payments, tasks and reviews read approval. Meeting links are not returned. A report past an internal read limit still answers with top-level truncated true. Its figures are then partial and can be too high or too low, so do not use them as totals. contacts.totalCapped, conversations.totalCountCapped and appointments.totalCountCapped mark a lifetime total that is partial. healthAlerts.unrespondedConversationsCapped marks threads that were not checked."
      parameters: [{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/agents:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsAgents
      tags: [Reports]
      summary: Agent performance
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Needs conversations:read, opportunities:read, appointments:read and users:read. Email addresses and avatars are not returned. A report past an internal read limit still answers with top-level truncated true. Its figures are then partial and can be too high or too low, so do not use them as totals."
      parameters: [{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/attribution:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsAttribution
      tags: [Reports]
      summary: Lead source attribution
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Needs contacts:read and opportunities:read. Grouped by the lead creation date. A report past an internal read limit still answers with top-level truncated true. Its figures are then partial and can be too high or too low, so do not use them as totals."
      parameters: [{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/paid-ads:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsPaidAds
      tags: [Reports]
      summary: Paid ads revenue
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Needs contacts:read, opportunities:read and call-history:read. Won opportunity value by close date, so revenue and spend for a window are not the same cohort. capped and truncated carry the same value: true means the figures are partial and can be too high or too low, so do not use them as totals."
      parameters: [{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/calendars:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsCalendars
      tags: [Reports]
      summary: Calendar analytics
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Needs appointments:read and calendars:read. Staff rows also need users:read. granularity is day, week or month. A report past an internal read limit still answers with top-level truncated true. Its figures are then partial and can be too high or too low, so do not use them as totals."
      parameters: [{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}},{"name":"calendarId","in":"query","required":false,"schema":{"type":"string"}},{"name":"granularity","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/product-revenue:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsProductRevenue
      tags: [Reports]
      summary: Product revenue
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Needs opportunities:read and products:read. A report past an internal read limit still answers with top-level truncated true. Its figures are then partial and can be too high or too low, so do not use them as totals."
      parameters: [{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}},{"name":"pipelineId","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/workflow-overview:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsWorkflowOverview
      tags: [Reports]
      summary: Workflow overview
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Needs workflows:read. Stored step errors are not returned. workflowsCapped and enrollmentsTruncated mark partial figures, which can be too high or too low."
      parameters: [{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/workflow-enrollments:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsWorkflowEnrollments
      tags: [Reports]
      summary: Workflow enrollment trend
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Needs workflows:read. truncated marks partial figures, which can be too high or too low."
      parameters: [{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/workflow-analytics/{id}:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsWorkflowAnalytics
      tags: [Reports]
      summary: Workflow analytics
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Needs workflows:read. Stored step errors are not returned."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/activity:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsActivity
      tags: [Reports]
      summary: Activity metrics
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Needs contacts:read. Reads at most 10,000 activities. Deleted contacts are left out of topContacts. A report past an internal read limit still answers with top-level truncated true. Its figures are then partial and can be too high or too low, so do not use them as totals. The newest rows in the window are kept."
      parameters: [{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/opportunity-sources:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsOpportunitySources
      tags: [Reports]
      summary: Opportunity sources
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Needs opportunities:read. Compares with the preceding window of equal length. A report past an internal read limit still answers with top-level truncated true. Its figures are then partial and can be too high or too low, so do not use them as totals."
      parameters: [{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/opportunity-funnel:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsOpportunityFunnel
      tags: [Reports]
      summary: Opportunity funnel by day
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Needs opportunities:read, invoices:read and payments:read. Days follow the location time zone. Revenue is what each invoice has collected so far, net of any refund to date, placed on the day the invoice was paid, whenever it was created. A later refund lowers that past day, and a fully refunded invoice drops out. The invoice report instead dates each payment and refund on the day the cash moved, and also counts external payments and part payments on invoices not yet settled. The two can differ, so do not expect them to match. A report past an internal read limit still answers with top-level truncated true. Its figures are then partial and can be too high or too low, so do not use them as totals."
      parameters: [{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/opportunity-sources-daily:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsOpportunitySourcesDaily
      tags: [Reports]
      summary: Opportunity sources by day
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Needs opportunities:read. The top six sources, with the rest grouped as Other. A report past an internal read limit still answers with top-level truncated true. Its figures are then partial and can be too high or too low, so do not use them as totals."
      parameters: [{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/activity-heartbeat:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsActivityHeartbeat
      tags: [Reports]
      summary: Activity heartbeat
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Needs contacts:read, conversations:read, appointments:read and opportunities:read. A report past an internal read limit still answers with top-level truncated true. Its figures are then partial and can be too high or too low, so do not use them as totals."
      parameters: [{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/audience:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsAudience
      tags: [Reports]
      summary: Audience growth
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Needs contacts:read and contact-lists:read. Refused above 200 lists. A report past an internal read limit still answers with top-level truncated true. Its figures are then partial and can be too high or too low, so do not use them as totals. lists[].truncated marks a list whose subscribed count is partial."
      parameters: [{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/email-deliverability:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsEmailDeliverability
      tags: [Reports]
      summary: Email deliverability
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. The window is whole UTC days, 1 to 366 days long. Needs campaigns:read. Rates per sending provider. data stays an array. When a read limit cut the rows meta.truncated is true. They are then partial and can be too high or too low, so do not use them as totals."
      parameters: [{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"type":"object","required":["truncated"],"properties":{"truncated":{"type":"boolean"}}}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/tasks:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsTasks
      tags: [Reports]
      summary: Task dashboard
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. Needs tasks:read. Reads the newest 5,000 tasks and the oldest 500 projects, each within a size limit. tasksCapped and projectsCapped mark bounded totals; truncated is true when either is."
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/reports/team-workload:
    get:
      x-seedly-oauth-scope: "reports:read"
      x-seedly-standard-scope: "reports:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportsTeamWorkload
      tags: [Reports]
      summary: Team workload
      description: "Location-wide aggregates computed by the native report after filtering to records this credential may open. OAuth follows the consenting user role and pipeline permissions. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. Needs tasks:read and users:read. At most 500 people; capped and truncated carry the same value: true means the figures are partial and can be too high or too low. Email addresses are not returned."
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '422':
          description: The report is too large to compute for this location. The message says whether a shorter date range can help.
        '429':
          description: Rate limit exceeded.
  /api/v1/report-exports:
    post:
      x-seedly-oauth-scope: "reports:export"
      x-seedly-standard-scope: "reports:export"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: postReportExports
      tags: [Reports]
      summary: Start a report export
      description: "Asynchronous export. Each bounded batch re-proves the original credential and token ceiling; losing authority stops the job and removes its output. Content is served only to the same credential until it expires. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. Also requires read approval for the exported records."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"kind":{"type":"string"}}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/report-exports/{id}:
    get:
      x-seedly-oauth-scope: "reports:export"
      x-seedly-standard-scope: "reports:export"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportExportsById
      tags: [Reports]
      summary: Read a report export
      description: "Asynchronous export. Each bounded batch re-proves the original credential and token ceiling; losing authority stops the job and removes its output. Content is served only to the same credential until it expires. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. Also requires read approval for the exported records."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/report-exports/{id}/content:
    get:
      x-seedly-oauth-scope: "reports:export"
      x-seedly-standard-scope: "reports:export"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getReportExportsByIdContent
      tags: [Reports]
      summary: Read report export content
      description: "Erasing a contact cancels every stored export of the location, with failure contact_erased. Asynchronous export. Each bounded batch re-proves the original credential and token ceiling; losing authority stops the job and removes its output. Content is served only to the same credential until it expires. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. Also requires read approval for the exported records."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"object","description":"One CSV part of the export.","required":["contentType","part","csv"],"properties":{"contentType":{"type":"string","const":"text/csv"},"part":{"type":"integer","minimum":0,"description":"Zero-based index of this part."},"csv":{"type":"string","description":"The CSV text of this part. Join the parts in order to rebuild the file."}}},"meta":{"type":"object","required":["limit","hasMore","cursor","truncated"],"properties":{"limit":{"type":"integer","const":1,"description":"Parts returned per call."},"hasMore":{"type":"boolean","description":"True when another part follows. This is the only stop signal."},"cursor":{"type":["string","null"],"description":"Pass as the cursor parameter to read the next part. Null on the last part."},"truncated":{"type":"boolean","description":"True when the job stopped at its 100,000 row limit, so the export is incomplete."}}}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/report-exports/{id}/cancel:
    post:
      x-seedly-oauth-scope: "reports:export"
      x-seedly-standard-scope: "reports:export"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: postReportExportsByIdCancel
      tags: [Reports]
      summary: Cancel a report export
      description: "Asynchronous export. Each bounded batch re-proves the original credential and token ceiling; losing authority stops the job and removes its output. Content is served only to the same credential until it expires. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. Also requires read approval for the exported records."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/report-exports/{id}/resume:
    post:
      x-seedly-oauth-scope: "reports:export"
      x-seedly-standard-scope: "reports:export"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: postReportExportsByIdResume
      tags: [Reports]
      summary: Resume a stalled report export
      description: "Asynchronous export. Each bounded batch re-proves the original credential and token ceiling; losing authority stops the job and removes its output. Content is served only to the same credential until it expires. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied. Also requires read approval for the exported records."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/audit-logs:
    get:
      x-seedly-oauth-scope: "audit:read"
      x-seedly-standard-scope: "audit:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getAuditLogs
      tags: [Audit]
      summary: List redacted audit history
      description: "Administrative read. Field values, IP addresses and user agents are redacted. Audit history cannot be changed through the API. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied."
      parameters: [{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}},{"name":"action","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string"}},{"name":"dateTo","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/audit-exports:
    post:
      x-seedly-oauth-scope: "audit:export"
      x-seedly-standard-scope: "audit:export"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: postAuditExports
      tags: [Audit]
      summary: Start a audit export
      description: "Asynchronous export. Each bounded batch re-proves the original credential and token ceiling; losing authority stops the job and removes its output. Content is served only to the same credential until it expires. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"dateFrom":{"type":"integer"},"dateTo":{"type":"integer"}}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/audit-exports/{id}:
    get:
      x-seedly-oauth-scope: "audit:export"
      x-seedly-standard-scope: "audit:export"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getAuditExportsById
      tags: [Audit]
      summary: Read a audit export
      description: "Asynchronous export. Each bounded batch re-proves the original credential and token ceiling; losing authority stops the job and removes its output. Content is served only to the same credential until it expires. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/audit-exports/{id}/content:
    get:
      x-seedly-oauth-scope: "audit:export"
      x-seedly-standard-scope: "audit:export"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getAuditExportsByIdContent
      tags: [Audit]
      summary: Read audit export content
      description: "Asynchronous export. Each bounded batch re-proves the original credential and token ceiling; losing authority stops the job and removes its output. Content is served only to the same credential until it expires. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"object","description":"One CSV part of the export.","required":["contentType","part","csv"],"properties":{"contentType":{"type":"string","const":"text/csv"},"part":{"type":"integer","minimum":0,"description":"Zero-based index of this part."},"csv":{"type":"string","description":"The CSV text of this part. Join the parts in order to rebuild the file."}}},"meta":{"type":"object","required":["limit","hasMore","cursor","truncated"],"properties":{"limit":{"type":"integer","const":1,"description":"Parts returned per call."},"hasMore":{"type":"boolean","description":"True when another part follows. This is the only stop signal."},"cursor":{"type":["string","null"],"description":"Pass as the cursor parameter to read the next part. Null on the last part."},"truncated":{"type":"boolean","description":"True when the job stopped at its 100,000 row limit, so the export is incomplete."}}}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/audit-exports/{id}/cancel:
    post:
      x-seedly-oauth-scope: "audit:export"
      x-seedly-standard-scope: "audit:export"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: postAuditExportsByIdCancel
      tags: [Audit]
      summary: Cancel a audit export
      description: "Asynchronous export. Each bounded batch re-proves the original credential and token ceiling; losing authority stops the job and removes its output. Content is served only to the same credential until it expires. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/audit-exports/{id}/resume:
    post:
      x-seedly-oauth-scope: "audit:export"
      x-seedly-standard-scope: "audit:export"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: postAuditExportsByIdResume
      tags: [Audit]
      summary: Resume a stalled audit export
      description: "Asynchronous export. Each bounded batch re-proves the original credential and token ceiling; losing authority stops the job and removes its output. Content is served only to the same credential until it expires. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/webhooks:
    get:
      x-seedly-oauth-scope: "webhooks:read"
      x-seedly-standard-scope: "webhooks:read"
      x-seedly-record-grant-approvals: {"minPolicyVersion":8,"options":["allowWebhooks"],"deletedEvents":{"minPolicyVersion":9,"option":"allowDeletedWebhooks","events":["task.deleted","opportunity.deleted"],"contactEvent":{"minPolicyVersion":10,"event":"contact.deleted"}},"linkedEvents":{"minPolicyVersion":14,"option":"allowLinkedEvents","events":["appointment.booked","appointment.cancelled","appointment.rescheduled","appointment.confirmed","appointment.completed","appointment.no_show","appointment.contact_deleted","task.contact_deleted","form.submitted","review.received"]}}
      x-seedly-resource-restrictions: {"oauth":["integration_owned"],"standard":["integration_owned"]}
      operationId: listWebhookSubscriptions
      tags: [Webhooks]
      summary: List webhook subscriptions
      responses:
        "200":
          description: List of webhook subscriptions
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/WebhookSubscription"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"

    post:
      x-seedly-oauth-scope: "webhooks:write"
      x-seedly-standard-scope: "webhooks:write"
      x-seedly-record-grant-approvals: {"minPolicyVersion":8,"options":["allowWebhooks"],"deletedEvents":{"minPolicyVersion":9,"option":"allowDeletedWebhooks","events":["task.deleted","opportunity.deleted"],"contactEvent":{"minPolicyVersion":10,"event":"contact.deleted"}},"linkedEvents":{"minPolicyVersion":14,"option":"allowLinkedEvents","events":["appointment.booked","appointment.cancelled","appointment.rescheduled","appointment.confirmed","appointment.completed","appointment.no_show","appointment.contact_deleted","task.contact_deleted","form.submitted","review.received"]}}
      x-seedly-resource-restrictions: {"oauth":["integration_owned"],"standard":["integration_owned"]}
      operationId: createWebhookSubscription
      tags: [Webhooks]
      summary: Create a webhook subscription
      description: |
        Subscribe to one or more event types. The response includes a `secret` field for
        HMAC-SHA256 signature verification. The secret is only shown once on creation.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookSubscriptionCreate"
            example:
              url: "https://your-server.com/webhooks/seedly"
              events: ["contact.created", "message.received"]
              description: "Chatbot integration"
      responses:
        "201":
          description: Subscription created (includes secret)
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    $ref: "#/components/schemas/WebhookSubscriptionWithSecret"
        "400":
          $ref: "#/components/responses/ValidationError"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"

  /api/v1/webhook-deliveries:
    get:
      x-seedly-oauth-scope: "webhook-deliveries:read"
      x-seedly-standard-scope: "webhook-deliveries:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getWebhookDeliveries
      tags: [Webhooks]
      summary: List delivery attempts for your subscription
      description: "Delivery status for a subscription this credential owns. subscriptionId is required. Payloads, response bodies and error text are not returned. Standard v2 or OAuth only; legacy keys and record-restricted grants are denied."
      parameters: [{"name":"subscriptionId","in":"query","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized result or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid request, unsupported query or missing idempotency key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval or authority outside current access.
        '404':
          description: Record or route unavailable.
        '409':
          description: Idempotency key reused with different details or state conflict.
        '429':
          description: Rate limit exceeded.
  /api/v1/webhooks/{id}:
    parameters:
      - name: id
        in: path
        required: true
        description: Webhook subscription ID
        schema:
          type: string
    patch:
      x-seedly-oauth-scope: "webhooks:write"
      x-seedly-standard-scope: "webhooks:write"
      x-seedly-record-grant-approvals: {"minPolicyVersion":8,"options":["allowWebhooks"],"deletedEvents":{"minPolicyVersion":9,"option":"allowDeletedWebhooks","events":["task.deleted","opportunity.deleted"],"contactEvent":{"minPolicyVersion":10,"event":"contact.deleted"}},"linkedEvents":{"minPolicyVersion":14,"option":"allowLinkedEvents","events":["appointment.booked","appointment.cancelled","appointment.rescheduled","appointment.confirmed","appointment.completed","appointment.no_show","appointment.contact_deleted","task.contact_deleted","form.submitted","review.received"]}}
      x-seedly-resource-restrictions: {"oauth":["integration_owned"],"standard":["integration_owned"]}
      operationId: updateWebhookSubscription
      tags: [Webhooks]
      summary: Update a webhook subscription
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookSubscriptionUpdate"
      responses:
        "200":
          description: Subscription updated
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: object
                    required: [id, updated]
                    properties:
                      id:
                        type: string
                      updated:
                        type: boolean
                        const: true
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

    delete:
      x-seedly-oauth-scope: "webhooks:delete"
      x-seedly-standard-scope: "webhooks:delete"
      x-seedly-record-grant-approvals: {"minPolicyVersion":8,"options":["allowWebhooks"],"deletedEvents":{"minPolicyVersion":9,"option":"allowDeletedWebhooks","events":["task.deleted","opportunity.deleted"],"contactEvent":{"minPolicyVersion":10,"event":"contact.deleted"}},"linkedEvents":{"minPolicyVersion":14,"option":"allowLinkedEvents","events":["appointment.booked","appointment.cancelled","appointment.rescheduled","appointment.confirmed","appointment.completed","appointment.no_show","appointment.contact_deleted","task.contact_deleted","form.submitted","review.received"]}}
      x-seedly-resource-restrictions: {"oauth":["integration_owned"],"standard":["integration_owned"]}
      operationId: deleteWebhookSubscription
      tags: [Webhooks]
      summary: Delete a webhook subscription
      responses:
        "200":
          description: Subscription deleted
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: object
                    required: [id, deleted]
                    properties:
                      id:
                        type: string
                      deleted:
                        type: boolean
                        const: true
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

  /api/v1/webhooks/{id}/regenerate-secret:
    parameters:
      - name: id
        in: path
        required: true
        description: Webhook subscription ID
        schema:
          type: string
    post:
      x-seedly-oauth-scope: "webhooks:write"
      x-seedly-standard-scope: "webhooks:write"
      x-seedly-record-grant-approvals: {"minPolicyVersion":8,"options":["allowWebhooks"],"deletedEvents":{"minPolicyVersion":9,"option":"allowDeletedWebhooks","events":["task.deleted","opportunity.deleted"],"contactEvent":{"minPolicyVersion":10,"event":"contact.deleted"}},"linkedEvents":{"minPolicyVersion":14,"option":"allowLinkedEvents","events":["appointment.booked","appointment.cancelled","appointment.rescheduled","appointment.confirmed","appointment.completed","appointment.no_show","appointment.contact_deleted","task.contact_deleted","form.submitted","review.received"]}}
      x-seedly-resource-restrictions: {"oauth":["integration_owned"],"standard":["integration_owned"]}
      operationId: regenerateWebhookSecret
      tags: [Webhooks]
      summary: Regenerate webhook secret
      description: Generates a new HMAC signing secret for the subscription. The old secret is immediately invalidated.
      responses:
        "200":
          description: New secret generated
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: object
                    required: [id, secret]
                    properties:
                      id:
                        type: string
                      secret:
                        type: string
                        description: New HMAC signing secret
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

  # =========================================================================
  # TASKS
  # =========================================================================
  /api/v1/tasks:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listTasks
      tags: [Tasks]
      summary: List tasks
      description: Returns tasks for the authenticated sub-account. Supports filters and cursor-based pagination. A page can be short or empty while hasMore is true. For Standard v2 and OAuth, meta.totalIsLowerBound is true when meta.total is a floor and false when it is exact.
      parameters:
        - in: query
          name: status
          schema:
            type: string
            enum: [todo, in_review, completed, cancelled]
        - in: query
          name: assignedTo
          schema: { type: string }
        - in: query
          name: contactId
          schema: { type: string }
        - in: query
          name: dealId
          schema: { type: string }
        - in: query
          name: dueBefore
          schema: { type: integer, format: int64, description: "Epoch ms - tasks due strictly before this timestamp" }
        - in: query
          name: dueAfter
          schema: { type: integer, format: int64, description: "Epoch ms - tasks due strictly after this timestamp" }
        - in: query
          name: limit
          schema: { type: integer, minimum: 1, maximum: 100, default: 50 }
        - in: query
          name: cursor
          schema: { type: string }
      responses:
        "200":
          description: List of tasks
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: array
                    items: { $ref: "#/components/schemas/Task" }
                  meta:
                    type: object
                    properties:
                      total: { type: integer }
                      hasMore: { type: boolean }
                      cursor: { type: string, nullable: true }
        "401": { $ref: "#/components/responses/Unauthorized" }
        "403": { $ref: "#/components/responses/Forbidden" }
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          description: Required for OAuth writes. Existing API-key requests retain their
            original behavior.
          schema:
            type: string
            minLength: 8
            maxLength: 128
            pattern: ^[A-Za-z0-9._:-]+$
      x-seedly-oauth-write-contract: OAuth requires Idempotency-Key (8-128 ASCII letters, digits, dot, underscore, colon or hyphen). Returns a minimal receipt; read permission is required to fetch records. API-key behavior is unchanged.
      operationId: createTask
      tags: [Tasks]
      summary: Create a task
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: "#/components/schemas/TaskCreate" }
      responses:
        "201":
          description: Task created
          content:
            application/json:
              schema:
                anyOf:
                  - type: object
                    required:
                      - data
                    properties:
                      data:
                        $ref: "#/components/schemas/Task"
                  - $ref: "#/components/schemas/OAuthWriteResponse"
        "400": { $ref: "#/components/responses/ValidationError" }
        "401": { $ref: "#/components/responses/Unauthorized" }
        "403": { $ref: "#/components/responses/Forbidden" }

  /api/v1/tasks/{id}:
    parameters:
      - in: path
        name: id
        required: true
        schema: { type: string }
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getTask
      tags: [Tasks]
      summary: Get a task
      responses:
        "200":
          description: Task
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data: { $ref: "#/components/schemas/Task" }
        "401": { $ref: "#/components/responses/Unauthorized" }
        "404": { $ref: "#/components/responses/NotFound" }
    patch:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-record-grant-approvals: {"minPolicyVersion":5,"options":["allowReassign","allowRelink"],"nullRemovalPolicyVersion":7,"nullRemovalFields":["assignedTo","contactId","dealId"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          description: Required for OAuth writes. Existing API-key requests retain their
            original behavior.
          schema:
            type: string
            minLength: 8
            maxLength: 128
            pattern: ^[A-Za-z0-9._:-]+$
      x-seedly-oauth-write-contract: OAuth requires Idempotency-Key (8-128 ASCII letters, digits, dot, underscore, colon or hyphen). Returns a minimal receipt; read permission is required to fetch records. API-key behavior is unchanged.
      operationId: updateTask
      tags: [Tasks]
      summary: Update a task
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: "#/components/schemas/TaskUpdate" }
      responses:
        "200":
          description: Task updated
          content:
            application/json:
              schema:
                anyOf:
                  - type: object
                    required:
                      - data
                    properties:
                      data:
                        $ref: "#/components/schemas/Task"
                  - $ref: "#/components/schemas/OAuthWriteResponse"
        "400": { $ref: "#/components/responses/ValidationError" }
        "401": { $ref: "#/components/responses/Unauthorized" }
        "404": { $ref: "#/components/responses/NotFound" }
    delete:
      x-seedly-oauth-scope: "tasks:delete"
      x-seedly-standard-scope: "tasks:delete"
      x-seedly-resource-restrictions: {"oauth":["location","record_grant_required"],"standard":["location"]}
      operationId: deleteTask
      parameters:
        - in: header
          name: Idempotency-Key
          required: false
          schema: { type: string, minLength: 8, maxLength: 128 }
          description: Required for restricted Standard v2 and OAuth deletion. OAuth requires version 4 restricted record consent. Unsupported cleanup is refused before effects. Legacy and unrestricted Standard keys retain their existing behavior.
      tags: [Tasks]
      summary: Delete a task
      responses:
        "200":
          description: Task deleted
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: object
                    properties:
                      id: { type: string }
                      deleted: { type: boolean }
        "401": { $ref: "#/components/responses/Unauthorized" }
        "404": { $ref: "#/components/responses/NotFound" }

  /api/v1/tasks/{id}/complete:
    parameters:
      - in: path
        name: id
        required: true
        schema: { type: string }
    put:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-record-grant-approvals: {"minPolicyVersion":6,"options":["allowLifecycle"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          description: Required for OAuth writes. Existing API-key requests retain their
            original behavior.
          schema:
            type: string
            minLength: 8
            maxLength: 128
            pattern: ^[A-Za-z0-9._:-]+$
      x-seedly-oauth-write-contract: OAuth requires Idempotency-Key (8-128 ASCII letters, digits, dot, underscore, colon or hyphen). Returns a minimal receipt; read permission is required to fetch records. API-key behavior is unchanged.
      operationId: completeTask
      tags: [Tasks]
      summary: Mark a task completed
      description: >-
        Sets status to `completed`. Recurrence is NOT scheduled here: `pmTasks` has
        no recurrence column (recurring work lives in `pmRecurringTasks`), so no
        new occurrence is created.
      responses:
        "200":
          description: Task completed
          content:
            application/json:
              schema:
                anyOf:
                  - type: object
                    required:
                      - data
                    properties:
                      data:
                        $ref: "#/components/schemas/Task"
                  - $ref: "#/components/schemas/OAuthWriteResponse"
        "401": { $ref: "#/components/responses/Unauthorized" }
        "404": { $ref: "#/components/responses/NotFound" }

  # =========================================================================
  # OPPORTUNITIES
  # =========================================================================
  /api/v1/opportunities:
    get:
      x-seedly-oauth-scope: "opportunities:read"
      x-seedly-standard-scope: "opportunities:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listOpportunities
      tags: [Opportunities]
      summary: List opportunities
      description: Returns opportunities for the authenticated sub-account. Supports filters and cursor-based pagination. A page can be short or empty while hasMore is true. For Standard v2 and OAuth, meta.totalIsLowerBound is true when meta.total is a floor and false when it is exact.
      parameters:
        - in: query
          name: pipelineId
          schema: { type: string }
        - in: query
          name: stageId
          schema: { type: string }
        - in: query
          name: contactId
          schema: { type: string }
        - in: query
          name: assignedTo
          schema: { type: string }
        - in: query
          name: status
          schema:
            type: string
            enum: [open, won, lost, abandoned]
        - in: query
          name: limit
          schema: { type: integer, minimum: 1, maximum: 100, default: 50 }
        - in: query
          name: cursor
          schema: { type: string }
      responses:
        "200":
          description: List of opportunities
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: array
                    items: { $ref: "#/components/schemas/Opportunity" }
                  meta:
                    type: object
                    properties:
                      total: { type: integer }
                      hasMore: { type: boolean }
                      cursor: { type: string, nullable: true }
        "401": { $ref: "#/components/responses/Unauthorized" }
        "403": { $ref: "#/components/responses/Forbidden" }
    post:
      x-seedly-oauth-scope: "opportunities:write"
      x-seedly-standard-scope: "opportunities:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          description: Required for OAuth writes. Existing API-key requests retain their
            original behavior.
          schema:
            type: string
            minLength: 8
            maxLength: 128
            pattern: ^[A-Za-z0-9._:-]+$
      x-seedly-oauth-write-contract: OAuth requires Idempotency-Key (8-128 ASCII letters, digits, dot, underscore, colon or hyphen). Returns a minimal receipt; read permission is required to fetch records. API-key behavior is unchanged.
      operationId: createOpportunity
      tags: [Opportunities]
      summary: Create an opportunity
      description: |
        Creates an opportunity in the specified pipeline stage. If the pipeline has
        `allowDuplicateOpportunities: false` and an open opportunity already exists for the
        same contact, the request fails with a `DUPLICATE_OPPORTUNITY` error.
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: "#/components/schemas/OpportunityCreate" }
      responses:
        "201":
          description: Opportunity created
          content:
            application/json:
              schema:
                anyOf:
                  - type: object
                    required:
                      - data
                    properties:
                      data:
                        $ref: "#/components/schemas/Opportunity"
                  - $ref: "#/components/schemas/OAuthWriteResponse"
        "400":
          description: Invalid request or duplicate opportunity
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              examples:
                validation_error:
                  value:
                    error:
                      code: "VALIDATION_ERROR"
                      message: "pipelineId, stageId, contactId, and name are required"
                duplicate_opportunity:
                  value:
                    error:
                      code: "DUPLICATE_OPPORTUNITY"
                      message: "An open opportunity already exists for this contact in this pipeline"
        "401": { $ref: "#/components/responses/Unauthorized" }
        "403": { $ref: "#/components/responses/Forbidden" }

  /api/v1/opportunities/{id}:
    parameters:
      - in: path
        name: id
        required: true
        schema: { type: string }
    get:
      x-seedly-oauth-scope: "opportunities:read"
      x-seedly-standard-scope: "opportunities:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getOpportunity
      tags: [Opportunities]
      summary: Get an opportunity
      responses:
        "200":
          description: Opportunity
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data: { $ref: "#/components/schemas/Opportunity" }
        "401": { $ref: "#/components/responses/Unauthorized" }
        "404": { $ref: "#/components/responses/NotFound" }
    patch:
      x-seedly-oauth-scope: "opportunities:write"
      x-seedly-standard-scope: "opportunities:write"
      x-seedly-record-grant-approvals: {"minPolicyVersion":5,"options":["allowReassign","allowRelink"],"nullRemovalPolicyVersion":7,"nullRemovalFields":["assignedTo"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          description: Required for OAuth writes. Existing API-key requests retain their
            original behavior.
          schema:
            type: string
            minLength: 8
            maxLength: 128
            pattern: ^[A-Za-z0-9._:-]+$
      x-seedly-oauth-write-contract: OAuth requires Idempotency-Key (8-128 ASCII letters, digits, dot, underscore, colon or hyphen). Returns a minimal receipt; read permission is required to fetch records. API-key behavior is unchanged.
      operationId: updateOpportunity
      tags: [Opportunities]
      summary: Update an opportunity
      description: Partial update. All fields are optional. To change status or move stages, prefer the dedicated `/status` and `/stage` endpoints.
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: "#/components/schemas/OpportunityUpdate" }
      responses:
        "200":
          description: Opportunity updated
          content:
            application/json:
              schema:
                anyOf:
                  - type: object
                    required:
                      - data
                    properties:
                      data:
                        $ref: "#/components/schemas/Opportunity"
                  - $ref: "#/components/schemas/OAuthWriteResponse"
        "400": { $ref: "#/components/responses/ValidationError" }
        "401": { $ref: "#/components/responses/Unauthorized" }
        "404": { $ref: "#/components/responses/NotFound" }
    delete:
      x-seedly-oauth-scope: "opportunities:delete"
      x-seedly-standard-scope: "opportunities:delete"
      x-seedly-resource-restrictions: {"oauth":["location","record_grant_required"],"standard":["location"]}
      operationId: deleteOpportunity
      parameters:
        - in: header
          name: Idempotency-Key
          required: false
          schema: { type: string, minLength: 8, maxLength: 128 }
          description: Required for restricted Standard v2 and OAuth deletion. OAuth requires version 4 restricted record consent. Unsupported cleanup is refused before effects. Legacy and unrestricted Standard keys retain their existing behavior.
      tags: [Opportunities]
      summary: Soft-delete an opportunity
      description: Sets `deletedAt` on the opportunity. Deleted opportunities are excluded from list and get responses.
      responses:
        "200":
          description: Opportunity deleted
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: object
                    properties:
                      id: { type: string }
                      deleted: { type: boolean }
        "401": { $ref: "#/components/responses/Unauthorized" }
        "404": { $ref: "#/components/responses/NotFound" }

  /api/v1/opportunities/{id}/status:
    parameters:
      - in: path
        name: id
        required: true
        schema: { type: string }
    put:
      x-seedly-oauth-scope: "opportunities:write"
      x-seedly-standard-scope: "opportunities:write"
      x-seedly-record-grant-approvals: {"minPolicyVersion":6,"options":["allowLifecycle"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          description: Required for OAuth writes. Existing API-key requests retain their
            original behavior.
          schema:
            type: string
            minLength: 8
            maxLength: 128
            pattern: ^[A-Za-z0-9._:-]+$
      x-seedly-oauth-write-contract: OAuth requires Idempotency-Key (8-128 ASCII letters, digits, dot, underscore, colon or hyphen). Returns a minimal receipt; read permission is required to fetch records. API-key behavior is unchanged.
      operationId: setOpportunityStatus
      tags: [Opportunities]
      summary: Set opportunity status
      description: Mark the opportunity as open, won, lost, or abandoned. When setting status to `lost`, `lostReason` is required.
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: "#/components/schemas/OpportunityStatusUpdate" }
      responses:
        "200":
          description: Opportunity status updated
          content:
            application/json:
              schema:
                anyOf:
                  - type: object
                    required:
                      - data
                    properties:
                      data:
                        $ref: "#/components/schemas/Opportunity"
                  - $ref: "#/components/schemas/OAuthWriteResponse"
        "400": { $ref: "#/components/responses/ValidationError" }
        "401": { $ref: "#/components/responses/Unauthorized" }
        "404": { $ref: "#/components/responses/NotFound" }

  /api/v1/opportunities/{id}/stage:
    parameters:
      - in: path
        name: id
        required: true
        schema: { type: string }
    put:
      x-seedly-oauth-scope: "opportunities:write"
      x-seedly-standard-scope: "opportunities:write"
      x-seedly-record-grant-approvals: {"minPolicyVersion":6,"options":["allowLifecycle"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          description: Required for OAuth writes. Existing API-key requests retain their
            original behavior.
          schema:
            type: string
            minLength: 8
            maxLength: 128
            pattern: ^[A-Za-z0-9._:-]+$
      x-seedly-oauth-write-contract: OAuth requires Idempotency-Key (8-128 ASCII letters, digits, dot, underscore, colon or hyphen). Returns a minimal receipt; read permission is required to fetch records. API-key behavior is unchanged.
      operationId: moveOpportunityStage
      tags: [Opportunities]
      summary: Move opportunity to a different stage
      description: Move the opportunity to a different stage within the same pipeline, with optional fractional-index neighbor hints (`beforeDealId`/`afterDealId`) to control the position within the destination stage's ordered list.
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: "#/components/schemas/OpportunityStageMove" }
      responses:
        "200":
          description: Opportunity moved
          content:
            application/json:
              schema:
                anyOf:
                  - type: object
                    required:
                      - data
                    properties:
                      data:
                        $ref: "#/components/schemas/Opportunity"
                  - $ref: "#/components/schemas/OAuthWriteResponse"
        "400": { $ref: "#/components/responses/ValidationError" }
        "401": { $ref: "#/components/responses/Unauthorized" }
        "404": { $ref: "#/components/responses/NotFound" }

  # =========================================================================
  # PIPELINES
  # =========================================================================
  /api/v1/opportunities/{id}/history:
    get:
      x-seedly-oauth-scope: "opportunities:read"
      x-seedly-standard-scope: "opportunities:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getOpportunityHistory
      tags: [Opportunities]
      summary: Read opportunity stage history
      description: "Oldest-first stage transitions for a live opportunity, returned as identifiers. changedByUserId is null when a Standard key wrote the row. changedByIntegration is true for every integration write, Standard or OAuth. attribution is known for those rows and unverified for all others. Unverified means the writer identity is not proven: it covers dashboard moves by real people, legacy keys and older rows, and such a row can name a fallback user. OAuth also needs live pipeline view access. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","required":["id","toStageId","changedAt"],"properties":{"id":{"type":"string"},"fromStageId":{"type":["string","null"]},"toStageId":{"type":"string"},"changedByUserId":{"type":["string","null"]},"changedByIntegration":{"type":"boolean"},"attribution":{"enum":["known","unverified"]},"changedAt":{"type":"string"}}}},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/opportunities/{id}/followers:
    get:
      x-seedly-oauth-scope: "opportunities:read"
      x-seedly-standard-scope: "opportunities:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getOpportunityFollowers
      tags: [Opportunities]
      summary: Read opportunity followers
      description: "Follower user identifiers, at most 10. Profiles are a separate directory read. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["id","userIds"],"properties":{"id":{"type":"string"},"userIds":{"type":"array","maxItems":10,"items":{"type":"string"}}}}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "opportunities:write"
      x-seedly-standard-scope: "opportunities:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: addOpportunityFollower
      tags: [Opportunities]
      summary: Add an opportunity follower
      description: "Adds one user who can reach this location, up to 10 followers. Followers receive the native opportunity notifications, so this is an explicit recipient change. Requires pipeline edit access for OAuth. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["userId"],"properties":{"userId":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/opportunities/{id}/followers/{userId}:
    delete:
      x-seedly-oauth-scope: "opportunities:write"
      x-seedly-standard-scope: "opportunities:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: removeOpportunityFollower
      tags: [Opportunities]
      summary: Remove an opportunity follower
      description: "Removes one follower. Removing a user who is not following succeeds without change. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/opportunities/{id}/products:
    get:
      x-seedly-oauth-scope: "opportunities:read"
      x-seedly-standard-scope: "opportunities:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listOpportunityProducts
      tags: [Opportunities]
      summary: List opportunity products
      description: "Line items on a live opportunity. Amounts are stored values, not a tax or payment calculation. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "opportunities:write"
      x-seedly-standard-scope: "opportunities:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: addOpportunityProduct
      tags: [Opportunities]
      summary: Add an opportunity product
      description: "Adds a line item, at most 200 per opportunity. A productId reference also requires products:read approval. The total is computed by the server and no invoice or payment is created. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name","quantity","unitPrice"],"properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":2000},"quantity":{"type":"number","minimum":0},"unitPrice":{"type":"number","minimum":0},"discount":{"type":"number","minimum":0,"maximum":100},"sortOrder":{"type":"integer"},"productId":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/opportunity-products/{id}:
    patch:
      x-seedly-oauth-scope: "opportunities:write"
      x-seedly-standard-scope: "opportunities:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateOpportunityProduct
      tags: [Opportunities]
      summary: Update an opportunity product
      description: "Partial line item update. The server recomputes the total when quantity, unit price or discount changes. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"minProperties":1,"properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":2000},"quantity":{"type":"number","minimum":0},"unitPrice":{"type":"number","minimum":0},"discount":{"type":"number","minimum":0,"maximum":100},"sortOrder":{"type":"integer"}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "opportunities:write"
      x-seedly-standard-scope: "opportunities:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: removeOpportunityProduct
      tags: [Opportunities]
      summary: Remove an opportunity product
      description: "Removes one line item from its parent opportunity. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/opportunities/{id}/restore:
    post:
      x-seedly-oauth-scope: "opportunities:write"
      x-seedly-standard-scope: "opportunities:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: restoreOpportunity
      tags: [Opportunities]
      summary: Restore a deleted opportunity
      description: "Restores a soft-deleted opportunity within its retention window. If its stage or pipeline was deleted, native placement moves it to the first available stage and the response reports relocated: true. OAuth needs edit access to the destination pipeline. Workflows do not re-run. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipelines/{id}/deleted-opportunities:
    get:
      x-seedly-oauth-scope: "opportunities:read"
      x-seedly-standard-scope: "opportunities:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listDeletedOpportunitiesInPipeline
      tags: [Opportunities]
      summary: List deleted opportunities in a pipeline
      description: "Newest deletions first, summary fields only. Opportunities whose pipeline was deleted are not listed here and remain restorable by identifier. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/opportunities/{id}/estimate:
    put:
      x-seedly-oauth-scope: "opportunities:financial-links"
      x-seedly-standard-scope: "opportunities:financial-links"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: linkOpportunityEstimate
      tags: [Opportunities]
      summary: Link an estimate to an opportunity
      description: "Separate financial-link approval. Sets the single linked estimate. Does not send, convert or charge. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["estimateId"],"properties":{"estimateId":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "opportunities:financial-links"
      x-seedly-standard-scope: "opportunities:financial-links"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: unlinkOpportunityEstimate
      tags: [Opportunities]
      summary: Unlink an estimate from an opportunity
      description: "Separate financial-link approval. Clears the link only; the estimate is unchanged. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/opportunities/{id}/invoice:
    put:
      x-seedly-oauth-scope: "opportunities:financial-links"
      x-seedly-standard-scope: "opportunities:financial-links"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: linkOpportunityInvoice
      tags: [Opportunities]
      summary: Link an invoice to an opportunity
      description: "Separate financial-link approval. Sets the single linked invoice. Does not send, charge or refund. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["invoiceId"],"properties":{"invoiceId":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "opportunities:financial-links"
      x-seedly-standard-scope: "opportunities:financial-links"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: unlinkOpportunityInvoice
      tags: [Opportunities]
      summary: Unlink an invoice from an opportunity
      description: "Separate financial-link approval. Clears the link only; the invoice is unchanged. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipelines/{id}/stats:
    get:
      x-seedly-oauth-scope: "opportunities:read"
      x-seedly-standard-scope: "opportunities:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getPipelineStats
      tags: [Pipelines]
      summary: Read pipeline KPIs
      description: "Live counts, value, weighted value, conversion rate and stale counts over a bounded newest-deal sample. truncated: true means the figures cover only that sample. Also requires pipelines:read. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipelines/{id}/analytics:
    get:
      x-seedly-oauth-scope: "opportunities:read"
      x-seedly-standard-scope: "opportunities:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getPipelineAnalytics
      tags: [Pipelines]
      summary: Read pipeline analytics
      description: "Stage conversion, time in stage, win rate, cycle time and forecast. Aging is aggregated per stage. dealsTruncated and historyTruncated disclose a partial sample. Also requires pipelines:read. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/opportunity-bulk-jobs:
    post:
      x-seedly-oauth-scope: "opportunities:write"
      x-seedly-standard-scope: "opportunities:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: startOpportunityBulkJobs
      tags: [Opportunities]
      summary: Start opportunity bulk job
      description: "Starts a durable job over at most 1000 pinned opportunities, processed in batches of 25. Each batch rechecks current authority and pipeline access. Native stage, status, workflow and notification effects run per record. Skipped records are counted by reason, a record that throws is listed in failedTargetIds and the job pauses after repeated failures. Completed work is not rolled back on pause or cancel. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["ids","action"],"properties":{"ids":{"type":"array","minItems":1,"maxItems":1000,"items":{"type":"string"}},"action":{"enum":["move_stage","set_status","assign","add_tags","remove_tags","change_pipeline"]},"stageId":{"type":"string"},"pipelineId":{"type":"string"},"status":{"enum":["open","won","lost","abandoned"]},"lostReason":{"type":"string","maxLength":500},"assignedTo":{"type":"string"},"tags":{"type":"array","minItems":1,"maxItems":20,"items":{"type":"string","maxLength":50}}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["id","accepted"],"properties":{"id":{"type":"string"},"accepted":{"const":true}}}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/opportunity-bulk-jobs/{id}:
    get:
      x-seedly-oauth-scope: "opportunities:write"
      x-seedly-standard-scope: "opportunities:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getOpportunityBulkJobs
      tags: [Opportunities]
      summary: Read opportunity bulk job progress
      description: "Progress for a job owned by this credential. Follow until status is complete, paused or cancelled. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["id","status","total","processed","succeeded","skipped"],"properties":{"id":{"type":"string"},"action":{"type":"string"},"status":{"enum":["running","paused","cancelled","complete"]},"total":{"type":"integer"},"processed":{"type":"integer"},"succeeded":{"type":"integer"},"skipped":{"type":"integer"},"skipReasons":{"type":"object","additionalProperties":{"type":"integer"}},"failedTargetIds":{"type":"array","maxItems":100,"items":{"type":"string"}},"skippedConsentTargetIds":{"type":"array","maxItems":1000,"items":{"type":"string"}},"failureCode":{"type":["string","null"]},"stalled":{"type":"boolean"},"partial":{"type":"boolean"}}}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/opportunity-bulk-jobs/{id}/resume:
    post:
      x-seedly-oauth-scope: "opportunities:write"
      x-seedly-standard-scope: "opportunities:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: resumeOpportunityBulkJobs
      tags: [Opportunities]
      summary: Resume opportunity bulk job
      description: "Resumes paused or stalled work with the current credential and requeues every target in failedTargetIds, including on a complete job. Refused with 409 when the job was created more than 72 hours ago or was cancelled, or when a job paused for a reason other than a system fault was last updated more than 24 hours ago. System faults are stalled_no_progress, batch_failed, prepare_failed and authorization_check_failed. A lost step is re-armed automatically, and a job with no progress after repeated checks pauses with failureCode stalled_no_progress. processed counts finished targets, so it stays honest during retries. A retried target that changed after the job was created is skipped as changed_since_job, except on consent jobs, where unrelated edits never cancel an opt-out. A narrower token stays narrower. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/opportunity-bulk-jobs/{id}/cancel:
    post:
      x-seedly-oauth-scope: "opportunities:write"
      x-seedly-standard-scope: "opportunities:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: cancelOpportunityBulkJobs
      tags: [Opportunities]
      summary: Cancel opportunity bulk job
      description: "Stops remaining batches for good. Completed changes stay in place. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/opportunity-bulk-deletions:
    post:
      x-seedly-oauth-scope: "opportunities:delete"
      x-seedly-standard-scope: "opportunities:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: startOpportunityBulkDeletions
      tags: [Opportunities]
      summary: Start opportunity bulk deletion
      description: "Starts a durable job over at most 1000 pinned opportunities, processed in batches of 25. Each batch rechecks current authority and pipeline access. Native stage, status, workflow and notification effects run per record. Skipped records are counted by reason, a record that throws is listed in failedTargetIds and the job pauses after repeated failures. Completed work is not rolled back on pause or cancel. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["ids"],"properties":{"ids":{"type":"array","minItems":1,"maxItems":1000,"items":{"type":"string"}}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["id","accepted"],"properties":{"id":{"type":"string"},"accepted":{"const":true}}}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/opportunity-bulk-deletions/{id}:
    get:
      x-seedly-oauth-scope: "opportunities:delete"
      x-seedly-standard-scope: "opportunities:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getOpportunityBulkDeletions
      tags: [Opportunities]
      summary: Read opportunity bulk deletion progress
      description: "Progress for a job owned by this credential. Follow until status is complete, paused or cancelled. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["id","status","total","processed","succeeded","skipped"],"properties":{"id":{"type":"string"},"action":{"type":"string"},"status":{"enum":["running","paused","cancelled","complete"]},"total":{"type":"integer"},"processed":{"type":"integer"},"succeeded":{"type":"integer"},"skipped":{"type":"integer"},"skipReasons":{"type":"object","additionalProperties":{"type":"integer"}},"failedTargetIds":{"type":"array","maxItems":100,"items":{"type":"string"}},"skippedConsentTargetIds":{"type":"array","maxItems":1000,"items":{"type":"string"}},"failureCode":{"type":["string","null"]},"stalled":{"type":"boolean"},"partial":{"type":"boolean"}}}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/opportunity-bulk-deletions/{id}/resume:
    post:
      x-seedly-oauth-scope: "opportunities:delete"
      x-seedly-standard-scope: "opportunities:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: resumeOpportunityBulkDeletions
      tags: [Opportunities]
      summary: Resume opportunity bulk deletion
      description: "Resumes paused or stalled work with the current credential and requeues every target in failedTargetIds, including on a complete job. Refused with 409 when the job was created more than 72 hours ago or was cancelled, or when a job paused for a reason other than a system fault was last updated more than 24 hours ago. System faults are stalled_no_progress, batch_failed, prepare_failed and authorization_check_failed. A lost step is re-armed automatically, and a job with no progress after repeated checks pauses with failureCode stalled_no_progress. processed counts finished targets, so it stays honest during retries. A retried target that changed after the job was created is skipped as changed_since_job, except on consent jobs, where unrelated edits never cancel an opt-out. A narrower token stays narrower. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/opportunity-bulk-deletions/{id}/cancel:
    post:
      x-seedly-oauth-scope: "opportunities:delete"
      x-seedly-standard-scope: "opportunities:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: cancelOpportunityBulkDeletions
      tags: [Opportunities]
      summary: Cancel opportunity bulk deletion
      description: "Stops remaining batches for good. Completed changes stay in place. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipelines/{id}/default:
    put:
      x-seedly-oauth-scope: "pipelines:write"
      x-seedly-standard-scope: "pipelines:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: setDefaultPipeline
      tags: [Pipelines]
      summary: Make a pipeline the default
      description: "Replaces the current default pipeline for this location. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipelines/{id}/copy:
    post:
      x-seedly-oauth-scope: "pipelines:write"
      x-seedly-standard-scope: "pipelines:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: copyPipeline
      tags: [Pipelines]
      summary: Copy a pipeline
      description: "Copies stages into a new non-default pipeline. Opportunities are not copied. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":200}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipelines/{id}/settings:
    patch:
      x-seedly-oauth-scope: "pipelines:write"
      x-seedly-standard-scope: "pipelines:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updatePipelineSettings
      tags: [Pipelines]
      summary: Update pipeline settings
      description: "Staleness and duplicate-opportunity behavior. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"minProperties":1,"properties":{"staleDealEnabled":{"type":"boolean"},"staleDealThresholdDays":{"type":"integer","minimum":1,"maximum":3650},"staleDealColor":{"type":"string","maxLength":32},"allowDuplicateOpportunities":{"type":"boolean"}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipeline-stages/{id}/settings:
    patch:
      x-seedly-oauth-scope: "pipelines:write"
      x-seedly-standard-scope: "pipelines:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updatePipelineStageSettings
      tags: [Pipelines]
      summary: Update stage gates and staleness
      description: "requiredFields are checked when opportunities move forward into the stage. A null staleDealThresholdDays clears the override. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"minProperties":1,"properties":{"requiredFields":{"type":"array","maxItems":50,"items":{"type":"string","maxLength":100}},"staleDealThresholdDays":{"type":["integer","null"],"minimum":1,"maximum":3650}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipeline-templates:
    post:
      x-seedly-oauth-scope: "pipelines:write"
      x-seedly-standard-scope: "pipelines:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: savePipelineTemplate
      tags: [Pipelines]
      summary: Save a pipeline as a template
      description: "Stores stage structure only. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["pipelineId","name"],"properties":{"pipelineId":{"type":"string"},"name":{"type":"string","maxLength":200},"description":{"type":"string","maxLength":2000}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
    get:
      x-seedly-oauth-scope: "pipelines:read"
      x-seedly-standard-scope: "pipelines:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listPipelineTemplates
      tags: [Pipelines]
      summary: List pipeline templates
      description: "Saved stage structures for this location. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipeline-templates/{id}/pipelines:
    post:
      x-seedly-oauth-scope: "pipelines:write"
      x-seedly-standard-scope: "pipelines:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createPipelineFromTemplate
      tags: [Pipelines]
      summary: Create a pipeline from a template
      description: "Creates a new non-default pipeline. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string","maxLength":200},"folderId":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipeline-folders:
    post:
      x-seedly-oauth-scope: "pipelines:write"
      x-seedly-standard-scope: "pipelines:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createPipelineFolder
      tags: [Pipelines]
      summary: Create a pipeline folder
      description: "Folders organize pipelines only. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string","maxLength":200},"parentId":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
    get:
      x-seedly-oauth-scope: "pipelines:read"
      x-seedly-standard-scope: "pipelines:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listPipelineFolders
      tags: [Pipelines]
      summary: List pipeline folders
      description: "Folders for this location. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipeline-folders/{id}:
    patch:
      x-seedly-oauth-scope: "pipelines:write"
      x-seedly-standard-scope: "pipelines:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updatePipelineFolder
      tags: [Pipelines]
      summary: Rename a pipeline folder
      description: "Renames one folder. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string","maxLength":200}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "pipelines:delete"
      x-seedly-standard-scope: "pipelines:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deletePipelineFolder
      tags: [Pipelines]
      summary: Delete a pipeline folder
      description: "Separate pipelines:delete approval. Contents move to the root; at most 200 pipelines and 200 child folders per request. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipelines/{id}/folder:
    put:
      x-seedly-oauth-scope: "pipelines:write"
      x-seedly-standard-scope: "pipelines:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: movePipelineToFolder
      tags: [Pipelines]
      summary: Move a pipeline to a folder
      description: "A null folderId moves it to the root. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["folderId"],"properties":{"folderId":{"type":["string","null"]}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipeline-scoring-rules:
    post:
      x-seedly-oauth-scope: "pipelines:write"
      x-seedly-standard-scope: "pipelines:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createPipelineScoringRule
      tags: [Pipelines]
      summary: Create a scoring rule
      description: "Rules are evaluated when scores are read. A rule without pipelineId applies to all pipelines. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name","conditions","scoreChange"],"properties":{"name":{"type":"string","maxLength":200},"description":{"type":"string","maxLength":2000},"pipelineId":{"type":"string"},"conditions":{"type":"array","maxItems":20,"items":{"type":"object"}},"scoreChange":{"type":"number","minimum":-100,"maximum":100},"isActive":{"type":"boolean"},"sortOrder":{"type":"integer"}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
    get:
      x-seedly-oauth-scope: "pipelines:read"
      x-seedly-standard-scope: "pipelines:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listPipelineScoringRules
      tags: [Pipelines]
      summary: List scoring rules
      description: "Rule definitions for this location. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipeline-scoring-rules/seed:
    post:
      x-seedly-oauth-scope: "pipelines:write"
      x-seedly-standard-scope: "pipelines:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: seedPipelineScoringRules
      tags: [Pipelines]
      summary: Seed default scoring rules
      description: "Adds the default rules only when the location has none. Returns the number seeded. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipeline-scoring-rules/{id}:
    patch:
      x-seedly-oauth-scope: "pipelines:write"
      x-seedly-standard-scope: "pipelines:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updatePipelineScoringRule
      tags: [Pipelines]
      summary: Update a scoring rule
      description: "Partial update. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"minProperties":1,"properties":{"name":{"type":"string","maxLength":200},"description":{"type":"string","maxLength":2000},"conditions":{"type":"array","maxItems":20,"items":{"type":"object"}},"scoreChange":{"type":"number","minimum":-100,"maximum":100},"isActive":{"type":"boolean"},"sortOrder":{"type":"integer"}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "pipelines:delete"
      x-seedly-standard-scope: "pipelines:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deletePipelineScoringRule
      tags: [Pipelines]
      summary: Delete a scoring rule
      description: "Separate pipelines:delete approval. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipelines/{id}/access/roles/{roleId}:
    put:
      x-seedly-oauth-scope: "pipelines:access"
      x-seedly-standard-scope: "pipelines:access"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: setPipelineRoleAccess
      tags: [Pipelines]
      summary: Set a role's pipeline access
      description: "Separate pipelines:access approval. OAuth cannot change a role above the authorizing user. Standard keys cannot change agency-level roles. This can lock people out of a pipeline. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"roleId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["access"],"properties":{"access":{"enum":["none","view","edit"]}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipelines/{id}/access/teams/{teamId}:
    put:
      x-seedly-oauth-scope: "pipelines:access"
      x-seedly-standard-scope: "pipelines:access"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: setPipelineTeamAccess
      tags: [Pipelines]
      summary: Set a team's pipeline access
      description: "Separate pipelines:access approval. The most restrictive applicable level wins. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"teamId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["access"],"properties":{"access":{"enum":["none","view","edit"]}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipelines/{id}/assignment-rules:
    put:
      x-seedly-oauth-scope: "pipelines:assignment"
      x-seedly-standard-scope: "pipelines:assignment"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: setPipelineAssignmentRules
      tags: [Pipelines]
      summary: Replace pipeline assignment rules
      description: "Separate pipelines:assignment approval. Replaces all rules and restarts round robin. Members who cannot reach this location are dropped. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["rules"],"properties":{"rules":{"type":"array","maxItems":20,"items":{"type":"object","required":["type"],"properties":{"type":{"type":"string","maxLength":50},"config":{"type":"object"}}}}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
    get:
      x-seedly-oauth-scope: "pipelines:assignment"
      x-seedly-standard-scope: "pipelines:assignment"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getPipelineAssignmentRules
      tags: [Pipelines]
      summary: Read pipeline assignment rules
      description: "Separate pipelines:assignment approval. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipelines/{id}/scores:
    get:
      x-seedly-oauth-scope: "pipelines:read"
      x-seedly-standard-scope: "pipelines:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listPipelineScores
      tags: [Pipelines]
      summary: List computed opportunity scores
      description: "Scores computed on read for live opportunities, from a base of 50 and clamped to 0 through 100. Also requires opportunities:read. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipelines/{id}/access:
    get:
      x-seedly-oauth-scope: "pipelines:access"
      x-seedly-standard-scope: "pipelines:access"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getPipelineAccess
      tags: [Pipelines]
      summary: Read pipeline access rows
      description: "Separate pipelines:access approval. Explicit role and team rows only; a role or team with no row has edit access. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/opportunities/{id}/field-values:
    get:
      x-seedly-oauth-scope: "opportunities:read"
      x-seedly-standard-scope: "opportunities:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getOpportunityFieldValues
      tags: [Opportunities]
      summary: Read opportunity field values
      description: "Values for active definitions, including textbox lists. File and signature values and reserved system keys are not returned. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "opportunities:write"
      x-seedly-standard-scope: "opportunities:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateOpportunityFieldValues
      tags: [Opportunities]
      summary: Update opportunity field values
      description: "Merges up to 100 values validated against active definitions, including textbox lists. File and signature values and reserved keys are refused. Native opportunity update effects apply. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["values"],"properties":{"values":{"type":"object","maxProperties":100}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/contacts/{id}/tags/add:
    post:
      x-seedly-oauth-scope: "contacts:write"
      x-seedly-standard-scope: "contacts:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: addContactTags
      tags: [Contacts]
      summary: Add contact tags
      description: "Adds up to 20 tags. Tags not already on the contact fire the native tag automation. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["tags"],"properties":{"tags":{"type":"array","minItems":1,"maxItems":20,"items":{"type":"string","minLength":1,"maxLength":50}}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/contacts/{id}/tags/remove:
    post:
      x-seedly-oauth-scope: "contacts:write"
      x-seedly-standard-scope: "contacts:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: removeContactTags
      tags: [Contacts]
      summary: Remove contact tags
      description: "Removes up to 20 tags. Tags actually removed fire the native tag automation. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["tags"],"properties":{"tags":{"type":"array","minItems":1,"maxItems":20,"items":{"type":"string","minLength":1,"maxLength":50}}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/opportunities/{id}/tags/add:
    post:
      x-seedly-oauth-scope: "opportunities:write"
      x-seedly-standard-scope: "opportunities:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: addOpportunityTags
      tags: [Opportunities]
      summary: Add opportunity tags
      description: "Case-insensitive add of up to 20 tags. Changes fire the native opportunity update. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["tags"],"properties":{"tags":{"type":"array","minItems":1,"maxItems":20,"items":{"type":"string","minLength":1,"maxLength":50}}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/opportunities/{id}/tags/remove:
    post:
      x-seedly-oauth-scope: "opportunities:write"
      x-seedly-standard-scope: "opportunities:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: removeOpportunityTags
      tags: [Opportunities]
      summary: Remove opportunity tags
      description: "Case-insensitive removal of up to 20 tags. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["tags"],"properties":{"tags":{"type":"array","minItems":1,"maxItems":20,"items":{"type":"string","minLength":1,"maxLength":50}}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/tags/{id}/associations:
    get:
      x-seedly-oauth-scope: "tags:read"
      x-seedly-standard-scope: "tags:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getTagAssociations
      tags: [Tags]
      summary: Read tag associations
      description: "Bounded counts and sample identifiers. Each section appears only with its own read approval: contacts:read, opportunities:read, pipelines:read. truncated: true means the count covers only a bounded sample. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/tag-folders:
    get:
      x-seedly-oauth-scope: "tags:read"
      x-seedly-standard-scope: "tags:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listTagFolders
      tags: [Tags]
      summary: List tag folders
      description: "Folders for this location. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "tags:write"
      x-seedly-standard-scope: "tags:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createTagFolder
      tags: [Tags]
      summary: Create a tag folder
      description: "Folders organize tags only. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string","maxLength":200},"parentId":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/tag-folders/{id}:
    patch:
      x-seedly-oauth-scope: "tags:write"
      x-seedly-standard-scope: "tags:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateTagFolder
      tags: [Tags]
      summary: Rename a tag folder
      description: "Renames one folder. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string","maxLength":200}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "tags:delete"
      x-seedly-standard-scope: "tags:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteTagFolder
      tags: [Tags]
      summary: Delete a tag folder
      description: "Separate tags:delete approval. Contents move to the root; at most 500 tags and 500 child folders per request. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/tags/{id}/folder:
    put:
      x-seedly-oauth-scope: "tags:write"
      x-seedly-standard-scope: "tags:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: moveTagToFolder
      tags: [Tags]
      summary: Move a tag to a folder
      description: "A null folderId moves it to the root. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["folderId"],"properties":{"folderId":{"type":["string","null"]}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/tags/usage-recount:
    post:
      x-seedly-oauth-scope: "tags:write"
      x-seedly-standard-scope: "tags:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: recountTagUsage
      tags: [Tags]
      summary: Recount tag usage
      description: "Starts the native background recount unless one finished recently. Returns fresh, started or running. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"status":{"enum":["fresh","started","running"]}}}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-bulk-jobs:
    post:
      x-seedly-oauth-scope: "contacts:write"
      x-seedly-standard-scope: "contacts:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: startContactBulkJob
      tags: [Contacts]
      summary: Start contact bulk job
      description: "Starts a durable job over at most 1000 pinned contacts, processed in batches of 25. Each batch rechecks current authority. Skips are counted by reason, a target that throws is listed in failedTargetIds and the job pauses after repeated failures. Completed work is not rolled back. Owner, consent, email and phone are not bulk editable here. Tag changes fire the native tag automation. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["ids","action"],"properties":{"ids":{"type":"array","minItems":1,"maxItems":1000,"items":{"type":"string"}},"action":{"enum":["add_tags","remove_tags","update_field"]},"tags":{"type":"array","minItems":1,"maxItems":20,"items":{"type":"string","maxLength":50}},"field":{"enum":["firstName","lastName","company","title","source","addressLine1","addressLine2","city","state","postalCode","country"]},"value":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["id","accepted"],"properties":{"id":{"type":"string"},"accepted":{"const":true}}}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-bulk-jobs/{id}:
    get:
      x-seedly-oauth-scope: "contacts:write"
      x-seedly-standard-scope: "contacts:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getContactBulkJob
      tags: [Contacts]
      summary: Read contact bulk job progress
      description: "Progress for a job owned by this credential. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["id","status","total","processed","succeeded","skipped"],"properties":{"id":{"type":"string"},"status":{"enum":["running","paused","cancelled","complete"]},"total":{"type":"integer"},"processed":{"type":"integer"},"succeeded":{"type":"integer"},"skipped":{"type":"integer"},"skipReasons":{"type":"object"},"failedTargetIds":{"type":"array","maxItems":100,"items":{"type":"string"}},"skippedConsentTargetIds":{"type":"array","maxItems":1000,"items":{"type":"string"}},"failureCode":{"type":["string","null"]},"stalled":{"type":"boolean"},"partial":{"type":"boolean"}}}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-bulk-jobs/{id}/resume:
    post:
      x-seedly-oauth-scope: "contacts:write"
      x-seedly-standard-scope: "contacts:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: resumeContactBulkJob
      tags: [Contacts]
      summary: Resume contact bulk job
      description: "Resumes paused or stalled work with the current credential and requeues every target in failedTargetIds, including on a complete job. Refused with 409 when the job was created more than 72 hours ago or was cancelled, or when a job paused for a reason other than a system fault was last updated more than 24 hours ago. System faults are stalled_no_progress, batch_failed, prepare_failed and authorization_check_failed. A lost step is re-armed automatically, and a job with no progress after repeated checks pauses with failureCode stalled_no_progress. processed counts finished targets, so it stays honest during retries. A retried target that changed after the job was created is skipped as changed_since_job, except on consent jobs, where unrelated edits never cancel an opt-out. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-bulk-jobs/{id}/cancel:
    post:
      x-seedly-oauth-scope: "contacts:write"
      x-seedly-standard-scope: "contacts:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: cancelContactBulkJob
      tags: [Contacts]
      summary: Cancel contact bulk job
      description: "Stops remaining batches for good. Completed changes stay in place. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-bulk-deletions:
    post:
      x-seedly-oauth-scope: "contacts:delete"
      x-seedly-standard-scope: "contacts:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: startContactBulkDeletion
      tags: [Contacts]
      summary: Start contact bulk deletion
      description: "Starts a durable job over at most 1000 pinned contacts, processed in batches of 25. Each batch rechecks current authority. Skips are counted by reason, a target that throws is listed in failedTargetIds and the job pauses after repeated failures. Completed work is not rolled back. Soft deletes contacts through the native deletion path, including deletion notifications. Deleted contacts are restored through the contact restore jobs. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["ids"],"properties":{"ids":{"type":"array","minItems":1,"maxItems":1000,"items":{"type":"string"}}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["id","accepted"],"properties":{"id":{"type":"string"},"accepted":{"const":true}}}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-bulk-deletions/{id}:
    get:
      x-seedly-oauth-scope: "contacts:delete"
      x-seedly-standard-scope: "contacts:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getContactBulkDeletion
      tags: [Contacts]
      summary: Read contact bulk deletion progress
      description: "Progress for a job owned by this credential. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["id","status","total","processed","succeeded","skipped"],"properties":{"id":{"type":"string"},"status":{"enum":["running","paused","cancelled","complete"]},"total":{"type":"integer"},"processed":{"type":"integer"},"succeeded":{"type":"integer"},"skipped":{"type":"integer"},"skipReasons":{"type":"object"},"failedTargetIds":{"type":"array","maxItems":100,"items":{"type":"string"}},"skippedConsentTargetIds":{"type":"array","maxItems":1000,"items":{"type":"string"}},"failureCode":{"type":["string","null"]},"stalled":{"type":"boolean"},"partial":{"type":"boolean"}}}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-bulk-deletions/{id}/resume:
    post:
      x-seedly-oauth-scope: "contacts:delete"
      x-seedly-standard-scope: "contacts:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: resumeContactBulkDeletion
      tags: [Contacts]
      summary: Resume contact bulk deletion
      description: "Resumes paused or stalled work with the current credential and requeues every target in failedTargetIds, including on a complete job. Refused with 409 when the job was created more than 72 hours ago or was cancelled, or when a job paused for a reason other than a system fault was last updated more than 24 hours ago. System faults are stalled_no_progress, batch_failed, prepare_failed and authorization_check_failed. A lost step is re-armed automatically, and a job with no progress after repeated checks pauses with failureCode stalled_no_progress. processed counts finished targets, so it stays honest during retries. A retried target that changed after the job was created is skipped as changed_since_job, except on consent jobs, where unrelated edits never cancel an opt-out. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-bulk-deletions/{id}/cancel:
    post:
      x-seedly-oauth-scope: "contacts:delete"
      x-seedly-standard-scope: "contacts:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: cancelContactBulkDeletion
      tags: [Contacts]
      summary: Cancel contact bulk deletion
      description: "Stops remaining batches for good. Completed changes stay in place. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-consent-bulk-jobs:
    post:
      x-seedly-oauth-scope: "consent:manage"
      x-seedly-standard-scope: "consent:manage"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: startContactConsentBulkJob
      tags: [Contacts]
      summary: Start contact consent bulk job
      description: "Starts a durable job over at most 1000 pinned contacts, processed in batches of 25. Each batch rechecks current authority. Skips are counted by reason, a target that throws is listed in failedTargetIds and the job pauses after repeated failures. Completed work is not rolled back. Records opt-outs only: it never grants consent or lifts an opt-out. A contact already opted out is skipped as no_change, keeps its existing provenance and gains no history row. The opt-out is withheld only when the channel's current status is a grant strictly newer than the job. Those contacts are listed in skippedConsentTargetIds, which sets partial, and the job continues. Any other status, or a grant with no provable time, is opted out. Each change writes a consent history row with the evidence source. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["ids","action","channel","source"],"properties":{"ids":{"type":"array","minItems":1,"maxItems":1000,"items":{"type":"string"}},"action":{"const":"opt_out"},"channel":{"enum":["email","sms","sms_marketing"]},"source":{"enum":["web_form","verbal","written","text_opt_in","import"]}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["id","accepted"],"properties":{"id":{"type":"string"},"accepted":{"const":true}}}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-consent-bulk-jobs/{id}:
    get:
      x-seedly-oauth-scope: "consent:manage"
      x-seedly-standard-scope: "consent:manage"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getContactConsentBulkJob
      tags: [Contacts]
      summary: Read contact consent bulk job progress
      description: "Progress for a job owned by this credential. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["id","status","total","processed","succeeded","skipped"],"properties":{"id":{"type":"string"},"status":{"enum":["running","paused","cancelled","complete"]},"total":{"type":"integer"},"processed":{"type":"integer"},"succeeded":{"type":"integer"},"skipped":{"type":"integer"},"skipReasons":{"type":"object"},"failedTargetIds":{"type":"array","maxItems":100,"items":{"type":"string"}},"skippedConsentTargetIds":{"type":"array","maxItems":1000,"items":{"type":"string"}},"failureCode":{"type":["string","null"]},"stalled":{"type":"boolean"},"partial":{"type":"boolean"}}}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-consent-bulk-jobs/{id}/resume:
    post:
      x-seedly-oauth-scope: "consent:manage"
      x-seedly-standard-scope: "consent:manage"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: resumeContactConsentBulkJob
      tags: [Contacts]
      summary: Resume contact consent bulk job
      description: "Resumes paused or stalled work with the current credential and requeues every target in failedTargetIds, including on a complete job. Refused with 409 when the job was created more than 72 hours ago or was cancelled, or when a job paused for a reason other than a system fault was last updated more than 24 hours ago. System faults are stalled_no_progress, batch_failed, prepare_failed and authorization_check_failed. A lost step is re-armed automatically, and a job with no progress after repeated checks pauses with failureCode stalled_no_progress. processed counts finished targets, so it stays honest during retries. A retried target that changed after the job was created is skipped as changed_since_job, except on consent jobs, where unrelated edits never cancel an opt-out. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-consent-bulk-jobs/{id}/cancel:
    post:
      x-seedly-oauth-scope: "consent:manage"
      x-seedly-standard-scope: "consent:manage"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: cancelContactConsentBulkJob
      tags: [Contacts]
      summary: Cancel contact consent bulk job
      description: "Stops remaining batches for good. Completed changes stay in place. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/contacts/{id}/lifecycle-stage:
    put:
      x-seedly-oauth-scope: "contacts:status"
      x-seedly-standard-scope: "contacts:status"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: setContactLifecycleStage
      tags: [Contacts]
      summary: Set contact lifecycle stage
      description: "Separate contacts:status approval. A change fires the lifecycle workflow trigger, and moving to customer or repeat ends running workflow and campaign enrollments. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["lifecycleStage"],"properties":{"lifecycleStage":{"enum":["lead","qualified","customer","repeat","inactive"]}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/contacts/{id}/assignment:
    put:
      x-seedly-oauth-scope: "contacts:assign"
      x-seedly-standard-scope: "contacts:assign"
      x-seedly-record-grant-approvals: {"minPolicyVersion":15,"options":["allowReassign"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: setContactAssignment
      tags: [Contacts]
      summary: Change or remove a contact owner
      description: "Separate contacts:assign approval for new scoped Standard v2 keys and new OAuth consent. Legacy API keys and existing approvals do not gain this operation. Own, team and selected grants also need the owner-change approval. The contact must be inside the grant before and after the change, and the new owner must be the approver or a current member of the approved team, so a My records grant cannot hand a contact away. Null removes the owner. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["assignedTo"],"properties":{"assignedTo":{"type":["string","null"]}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-notes/{id}/details:
    get:
      x-seedly-oauth-scope: "contacts:read"
      x-seedly-standard-scope: "contacts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getContactNoteDetails
      tags: [Contacts]
      summary: Read note mentions and attachments
      description: "Mentioned user identifiers and attachment metadata. Never a storage URL. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-notes/{id}/attachments/{index}:
    get:
      x-seedly-oauth-scope: "contacts:read"
      x-seedly-standard-scope: "contacts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getContactNoteAttachment
      tags: [Contacts]
      summary: Download a note attachment
      description: "Authenticated bytes for one allowed attachment, at most 25 MB, recorded in the audit log. Attachment upload is not part of this operation. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"index","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Attachment bytes."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-notes/{id}/attachments:
    post:
      x-seedly-oauth-scope: "contact-notes:attach"
      x-seedly-standard-scope: "contact-notes:attach"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: attachContactNoteFile
      tags: [Contacts]
      summary: Attach a file to a note
      description: "Upload through the files API first, then name the file here. Needs contact-notes:attach and the exact files:read approval. The file must be readable, owned by this location, and unlinked or linked to this contact; it is then linked to the contact. Deleting the note removes the attached bytes, as it does in the dashboard. A note has at most 20 attachments. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["fileId"],"properties":{"fileId":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/contact-notes/{id}/mentions:
    post:
      x-seedly-oauth-scope: "contact-notes:mention"
      x-seedly-standard-scope: "contact-notes:mention"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: addContactNoteMentions
      tags: [Contacts]
      summary: Mention users on a note
      description: "Separate contact-notes:mention approval because it notifies people. Adds up to 50 users, notifying only users newly mentioned who can reach this location. Others are skipped, and the response does not say which. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["userIds"],"properties":{"userIds":{"type":"array","minItems":1,"maxItems":50,"items":{"type":"string"}}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"const":true}}}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/activities:
    get:
      x-seedly-oauth-scope: "contacts:read"
      x-seedly-standard-scope: "contacts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listRecentActivities
      tags: [Contacts]
      summary: List recent activity
      description: "Newest first, summary categories only. Source content is read through the source route. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/activities/{id}:
    get:
      x-seedly-oauth-scope: "contacts:read"
      x-seedly-standard-scope: "contacts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getActivity
      tags: [Contacts]
      summary: Read one activity
      description: "Summary plus source identifiers, each present only with that source's own read approval. Never raw descriptions or metadata. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/opportunities/{id}/activity:
    get:
      x-seedly-oauth-scope: "opportunities:read"
      x-seedly-standard-scope: "opportunities:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listOpportunityActivity
      tags: [Opportunities]
      summary: List opportunity activity
      description: "Newest first, summary categories only. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/companies/{id}/related:
    get:
      x-seedly-oauth-scope: "companies:read"
      x-seedly-standard-scope: "companies:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getCompanyRelated
      tags: [Companies]
      summary: Read company related records
      description: "invoices appears with the exact invoices:read approval: count, totalByCurrency and paidByCurrency in major units, leaving void invoices out of the money and stopping at a byte budget, reported by truncated. Bounded counts over linked contacts. Contact, opportunity and conversation sections each need their own read approval. Opportunity value is open deals only, grouped by currency. truncated: true means counts cover a bounded sample. Invoice rollups are not included. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/contacts/{id}/list-field-values:
    get:
      x-seedly-oauth-scope: "contacts:read"
      x-seedly-standard-scope: "contacts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getContactListFieldValues
      tags: [Contacts]
      summary: Read contact list field values
      description: "Textbox list values only. The scalar field-values routes are unchanged and never return arrays. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "contacts:write"
      x-seedly-standard-scope: "contacts:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateContactListFieldValues
      tags: [Contacts]
      summary: Update contact list field values
      description: "Merges up to 100 textbox list values, each at most 100 strings of 1000 characters. Null clears a value. Location-wide Standard v2 or OAuth only; own, team and selected grants, legacy API keys and existing approvals do not gain this operation. Requires Idempotency-Key. A replay rechecks current authority and returns the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["values"],"properties":{"values":{"type":"object","maxProperties":100}}}}}}
      responses:
        '200':
          description: "Authorized result or durable write receipt."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid payload, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted record grant or current access refused.
        '404':
          description: Unknown route or record outside this location.
        '409':
          description: Current state conflict or Idempotency-Key reused with a different request.
        '429':
          description: Rate limit exceeded.
  /api/v1/pipelines:
    get:
      x-seedly-oauth-scope: "pipelines:read"
      x-seedly-standard-scope: "pipelines:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listPipelines
      tags: [Pipelines]
      summary: List pipelines
      description: Returns pipelines for the authenticated sub-account, each with its ordered list of stages, 100 per request in creation order. Standard v2 and OAuth continue with meta.cursor while meta.hasMore is true; a cursor from another credential is refused with 400. Legacy keys receive the first 100 with no meta.
      parameters:
        - name: cursor
          in: query
          description: Standard v2 and OAuth only. The meta.cursor of the previous page.
          schema: { type: string }
      responses:
        "200":
          description: List of pipelines
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: array
                    items: { $ref: "#/components/schemas/Pipeline" }
                  meta:
                    description: Standard v2 and OAuth only. Absent for legacy keys.
                    type: object
                    properties:
                      hasMore: { type: boolean }
                      cursor: { type: ["string", "null"] }
        "401": { $ref: "#/components/responses/Unauthorized" }
        "403": { $ref: "#/components/responses/Forbidden" }

  # =========================================================================
  # CAMPAIGNS
  # =========================================================================
    post:
      x-seedly-oauth-scope: "pipelines:write"
      x-seedly-standard-scope: "pipelines:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createIntegrationPipeline
      tags: [Pipelines]
      summary: "Create a pipeline"
      description: "Explicitly approved location-wide Standard v2 or OAuth only. Legacy API keys and own/team/selected grants cannot use this operation. Requires pipelines:write, with pipelines and deals create/update role authority. Existing pipelines additionally require live edit access through their pipeline ACL and an active approving user/membership. No owner, ACL, default-setting, deal-movement or deletion operation is included. Requires a stable Idempotency-Key. Unknown body fields are rejected. Current authorization and target eligibility are checked before retry receipts are returned; retries do not reapply the mutation. Writes return only an identifier and created/updated receipt, not record content. Creates the six default stages Lead, Qualified, Proposal, Negotiation, Won and Lost; Won/Lost are terminal. The first pipeline in a location becomes the default. Pipeline names are trimmed and capped at 200 characters; descriptions at 5000."
      parameters: [{"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"name": {"type": "string", "minLength": 1, "maxLength": 200}, "description": {"type": "string", "maxLength": 5000}}, "required": ["name"]}}}}
      responses:
        '200':
          description: Authorized metadata or an idempotent write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationValueWriteReceipt"}}}}}
        '400':
          description: Invalid request or ineligible current record state.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale approval, unsupported record restriction or revoked access.
        '404':
          description: Resource not available in this location.
        '409':
          description: Idempotency key reused with different request details.
        '413':
          description: Request body exceeds the byte limit.
        '415':
          description: Write request must use application/json.
        '429':
          description: Rate limit exceeded.
  /api/v1/campaigns:
    get:
      x-seedly-oauth-scope: "campaigns:read"
      x-seedly-standard-scope: "campaigns:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listIntegrationCampaigns
      tags: [Campaigns]
      summary: List email campaigns with a standard key or OAuth grant
      description: Requires campaigns:read. Legacy campaign-write keys do not acquire read access.
      parameters:
        - {
            name: limit,
            in: query,
            schema: { type: integer, minimum: 1, maximum: 100, default: 50 },
          }
        - { name: cursor, in: query, schema: { type: string } }
      responses:
        '200':
          description: Data is an array of campaign summaries. Meta contains hasMore and cursor. Summaries omit bodyHtml; use the single-campaign read for the rendered body.
        '403':
          description: Missing read scope or approval
    post:
      x-seedly-oauth-scope: "campaigns:write"
      x-seedly-standard-scope: "campaigns:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          description: Required for standard v2 keys and OAuth; optional for legacy keys.
          schema:
            type: string
            minLength: 8
            maxLength: 128
            pattern: '^[A-Za-z0-9._:-]+$'
      operationId: createCampaign
      tags: [Campaigns]
      summary: Create a draft email campaign from a stored layout
      description: |
        Creates a **draft** email broadcast whose body is a stored layout template
        spliced with the supplied content HTML.

        The layout is an email template whose `bodyHtml` contains exactly one
        `{{content}}` placeholder. The layout should also carry
        `{{utility.unsubscribe_link}}` in its own footer - without it, a full HTML
        document gets the CAN-SPAM footer appended after `</html>`, and this
        endpoint rejects the request rather than producing malformed mail.

        This endpoint only creates - a retry of this request cannot mail anyone.
        Sending is a separate call (`POST /api/v1/campaigns/{id}/send`).

        There is no test-send endpoint. To preview before an irreversible send,
        open the draft in the dashboard and use Preview & Test.

        Requires `campaigns:send` for standard v2 keys and OAuth, or the existing `campaigns:write` scope for legacy keys. New-model requests require Idempotency-Key; identical retries return the original result and conflicting payloads return 409.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [name, subject, contentHtml, layout]
              properties:
                name:
                  type: string
                  description: Internal campaign name (not shown to recipients).
                  example: August promo
                subject:
                  type: string
                  example: 'Your August offer is here'
                contentHtml:
                  type: string
                  description: Inner content HTML, spliced into the layout's `{{content}}` slot.
                  example: '<h1>Hello</h1><p>Body copy</p>'
                layout:
                  type: string
                  description: Name of the email template to use as the layout.
                  example: default
                listId:
                  type: string
                  description: >
                    REQUIRED. The List the campaign sends to, which also scopes
                    unsubscribes. There is no fallback: no shipped surface writes a
                    default list onto a layout template, and this endpoint validates
                    the list at CREATE time rather than at send.
                preheader:
                  type: string
      responses:
        '201':
          description: Draft campaign created
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: object
                    properties:
                      id: { type: string }
                      status: { type: string, example: draft }
        '400':
          description: |
            Validation error. `message` carries a prefixed reason:
            `layout_not_found:`, `layout_invalid:`, `list_required:` or
            `feature_unavailable:`.
          $ref: '#/components/responses/ValidationError'
        '401': { $ref: '#/components/responses/Unauthorized' }
        '403': { $ref: '#/components/responses/Forbidden' }

  /api/v1/campaigns/{id}:
    delete:
      x-seedly-oauth-scope: "campaigns:delete"
      x-seedly-standard-scope: "campaigns:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteCampaign
      tags: [Campaigns]
      summary: "Delete a campaign"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. SMS campaigns additionally require campaigns:sms. Requires campaigns:delete. Refused while sending. Cancels any scheduled send; recipients are removed in bounded batches. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.
    get:
      x-seedly-oauth-scope: "campaigns:read"
      x-seedly-standard-scope: "campaigns:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getIntegrationCampaign
      tags: [Campaigns]
      summary: Read one email campaign
      description: Requires campaigns:read on a standard API key or OAuth grant.
      parameters:
        - { name: id, in: path, required: true, schema: { type: string } }
      responses:
        '200':
          description: Email campaign details, including subject and rendered bodyHtml
        '404':
          description: Campaign unavailable in this location

    patch:
      x-seedly-oauth-scope: "campaigns:write"
      x-seedly-standard-scope: "campaigns:write"
      x-seedly-standard-operation-permissions: [["campaigns","update"]]
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateIntegrationCampaignDraft
      tags: [Campaigns]
      summary: "Edit an unscheduled email broadcast draft"
      description: "Explicitly approved location-wide Standard v2 or OAuth only. Legacy API keys and own/team/selected grants cannot use this operation. Requires the newly approved campaigns:write route plus current campaigns:update authority with all-record scope. The existing campaigns:write role/signature for campaign creation remains unchanged; this extra live check applies only to PATCH. Requires a stable Idempotency-Key. Unknown body fields are rejected. Current authorization and target eligibility are checked before retry receipts are returned; retries do not reapply the mutation. Writes return only an identifier and created/updated receipt, not record content. Only unarchived draft email broadcasts with no schedule, send authorization, recipient population, recipient rows, recipients or prior sends are editable. Allowed fields are name, subject, preheader and contentHtml. Audience, sender, layout selection, status and scheduling cannot change. contentHtml requires an HTML-mode campaign with consistent stored source/rendered HTML. Layout-backed content additionally requires templates:read and a currently accessible shared local layout that still reproduces the saved body; a changed/unavailable layout rejects the edit. Content is sanitized with the email profile and rendered through the existing layout. No sending, scheduling or recipient population occurs. HTTP JSON bodies are capped at 1 MiB; source and rendered HTML are each capped at 500000 characters."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"name": {"type": "string", "minLength": 1, "maxLength": 255}, "subject": {"type": "string", "maxLength": 1000}, "preheader": {"type": "string", "maxLength": 1000}, "contentHtml": {"type": "string", "maxLength": 500000}}, "minProperties": 1}}}}
      responses:
        '200':
          description: Authorized metadata or an idempotent write receipt.
          content: {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/IntegrationValueWriteReceipt"}}}}}
        '400':
          description: Invalid request or ineligible current record state.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale approval, unsupported record restriction or revoked access.
        '404':
          description: Resource not available in this location.
        '409':
          description: Idempotency key reused with different request details.
        '413':
          description: Request body exceeds the byte limit.
        '415':
          description: Write request must use application/json.
        '429':
          description: Rate limit exceeded.
  /api/v1/campaigns/{id}/send:
    post:
      x-seedly-oauth-scope: "campaigns:send"
      x-seedly-standard-scope: "campaigns:send"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: sendCampaign
      tags: [Campaigns]
      summary: Send a draft campaign immediately
      description: |
        Moves a `draft` or `scheduled` email campaign to `sending` and starts the
        send pipeline. Any previously-armed scheduled send is cancelled first, so
        a campaign cannot go out twice.

        Email campaigns only - an SMS broadcast is refused, because the bulk-SMS
        capability check the dashboard applies has no meaning for an API key.

        Requires `campaigns:send` for standard v2 keys and OAuth, or the existing `campaigns:write` scope for legacy keys. New-model requests require Idempotency-Key; identical retries return the original result and conflicting payloads return 409.
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          description: Required for standard v2 keys and OAuth; optional for legacy keys.
          schema:
            type: string
            minLength: 8
            maxLength: 128
            pattern: '^[A-Za-z0-9._:-]+$'
        - name: id
          in: path
          required: true
          schema: { type: string }
      responses:
        '200':
          description: Campaign is sending
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id: { type: string }
                      status: { type: string, example: sending }
        '400':
          description: |
            `invalid_status:` (not draft/scheduled), `channel_unsupported:`
            (not an email campaign), `list_required:` (no list set), or
            `empty_audience:` (the audience resolves to nobody who can be
            contacted on this channel). The audience is resolved BEFORE the
            campaign moves to `sending`, so a `200` here means real recipients
            were found - it never reports `sending` for a campaign that will
            silently revert to draft.
          $ref: '#/components/responses/ValidationError'
        '401': { $ref: '#/components/responses/Unauthorized' }
        '403': { $ref: '#/components/responses/Forbidden' }
        '404': { $ref: '#/components/responses/NotFound' }

  /api/v1/campaigns/{id}/schedule:
    post:
      x-seedly-oauth-scope: "campaigns:send"
      x-seedly-standard-scope: "campaigns:send"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: scheduleCampaign
      tags: [Campaigns]
      summary: Schedule a draft campaign
      description: |
        Arms a `draft` email campaign to send at `scheduledAt`. A timestamp in the
        past fires immediately rather than arming nothing - a campaign that shows
        "Scheduled" but never sends is the worse failure.

        Requires `campaigns:send` for standard v2 keys and OAuth, or the existing `campaigns:write` scope for legacy keys. New-model requests require Idempotency-Key; identical retries return the original result and conflicting payloads return 409.
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          description: Required for standard v2 keys and OAuth; optional for legacy keys.
          schema:
            type: string
            minLength: 8
            maxLength: 128
            pattern: '^[A-Za-z0-9._:-]+$'
        - name: id
          in: path
          required: true
          schema: { type: string }
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [scheduledAt]
              properties:
                scheduledAt:
                  type: integer
                  format: int64
                  description: Epoch milliseconds.
                  example: 1786000000000
      responses:
        '200':
          description: Campaign scheduled
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id: { type: string }
                      status: { type: string, example: scheduled }
        '400':
          description: Missing/invalid `scheduledAt`, or the campaign is not a draft.
          $ref: '#/components/responses/ValidationError'
        '401': { $ref: '#/components/responses/Unauthorized' }
        '403': { $ref: '#/components/responses/Forbidden' }
        '404': { $ref: '#/components/responses/NotFound' }

  # =========================================================================
  # SUB-ACCOUNTS
  # =========================================================================

  /api/v1/sub-accounts:
    get:
      operationId: listSubAccounts
      tags: [Sub-Accounts]
      summary: List sub-accounts (agency-scoped keys only)
      description: |
        Returns all active sub-accounts under the agency. Only accessible with agency-scoped API keys.
      responses:
        "200":
          description: List of sub-accounts
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/SubAccount"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"

  # =========================================================================
  # CONVERSATIONAL BOOKING (AI SETTER)
  #
  # Two reads a booking bot needs and nothing else. They are deliberately not
  # the products and estimates resources: each returns the smallest set of
  # fields the conversation needs, because these keys are handed to a
  # third-party bot vendor.
  # =========================================================================
  /api/v1/booking/service-types:
    get:
      x-seedly-oauth-scope: "calendars:read"
      x-seedly-standard-scope: "calendars:read"
      x-seedly-resource-restrictions: {"oauth":["published_catalog"],"standard":["published_catalog"]}
      operationId: listBookingServiceTypes
      tags: [Conversational booking]
      summary: List the services this location sells, with prices
      description: |
        The published price list, so a booking conversation can answer "what
        does a drain clean cost" instead of stalling.

        This is a business read. The answer is the same whoever asks, so it is
        safe to serve to a chat widget that identifies nobody.

        Serve it from YOUR WIDGET'S SERVER, not from the browser. An API key
        belongs on a server: keys are not scoped to a single endpoint, so a
        key in page JavaScript hands every visitor whatever else that key can
        reach, and `/api/v1/*` sends no CORS headers, so a browser call would
        be blocked anyway.

        Only services that are currently on sale are returned. A retired
        service is absent rather than flagged, so a bot cannot quote something
        the business stopped selling.

        `hasVariablePricing` is `true` when the price depends on quantity or on
        options the customer chooses. Treat `price` as a starting point in that
        case and offer a proper quote rather than a firm number. The pricing
        matrix itself is not published.

        Deliberately absent: SKU, images, tax category, payment-provider
        linkage, and the tier or option matrix.

        Requires the `service-types:read` scope.
      parameters:
        - name: search
          in: query
          required: false
          description: |
            Match against the service name. Up to 100 characters. An empty or
            whitespace-only value is treated as no filter.
          schema:
            type: string
            maxLength: 100
        - name: limit
          in: query
          required: false
          description: How many services to return. Whole number, 1 to 100.
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 50
      responses:
        "200":
          description: The price list
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
            X-RateLimit-Limit:
              $ref: "#/components/headers/X-RateLimit-Limit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/X-RateLimit-Remaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/X-RateLimit-Reset"
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: array
                    items: { $ref: "#/components/schemas/ServiceType" }
                  meta:
                    type: object
                    required: [total, hasMore, limit, search]
                    properties:
                      total:
                        type: integer
                        description: How many services this response carries.
                      hasMore:
                        type: boolean
                        description: |
                          Whether more services matched than the page could
                          carry. Narrow with `search` or raise `limit`.
                      truncated:
                        type: boolean
                        description: |
                          Standard v2 and OAuth only, always present. True when the
                          500-row scan (100 for `search`) or `limit` stopped the answer,
                          with `hasMore` true. No cursor continues this list.
                      limit:
                        type: integer
                        description: The page size this request was served at.
                      search:
                        type: string
                        nullable: true
                        description: |
                          The search this answer was filtered by, trimmed
                          exactly as it was run, or `null` when nothing was
                          filtered.

                          **Read this before you treat an empty `data` as an
                          answer.** `search: null` with `total: 0` means this
                          location has published no price list at all. A string
                          with `total: 0` means nothing matched that word, and
                          the catalogue may be full of other things. The two
                          used to be byte-identical, so a bot had to guess which
                          it was and then say the guess out loud to a customer.
              example:
                data: []
                meta:
                  total: 0
                  hasMore: false
                  limit: 50
                  search: "submarine"
        "400": { $ref: "#/components/responses/ValidationError" }
        "401": { $ref: "#/components/responses/Unauthorized" }
        "403": { $ref: "#/components/responses/Forbidden" }
        "429": { $ref: "#/components/responses/RateLimited" }

  /api/v1/booking/estimates:
    get:
      x-seedly-standard-scope: "estimates:read"
      x-seedly-resource-restrictions: {"standard":["verified_customer"]}
      operationId: listBookingEstimates
      tags: [Conversational booking]
      summary: Quotes belonging to the contact a conversation is already with
      description: |
        ## Read this before you wire it up

        `contactId` MUST come from the CRM contact id your bot platform already
        holds for the conversation, as a **source field variable**. This CRM
        sends that id to your bot on every inbound message, so the value is
        never collected from anything the customer said and the customer cannot
        change it by talking.

        Wiring the same field as a bot **custom parameter** (a value the
        platform describes as something you need the AI to collect) breaks the
        entire design. The AI would then fill it from the conversation, and the
        request would be perfectly valid and about the wrong person. Nothing on
        this side can tell those two apart once the value is a real id, so this
        is a configuration you have to get right rather than one this endpoint
        can police.

        What this endpoint does do about it: it refuses any value that is not a
        contact id this CRM could have issued, with an error that says so. That
        check decodes the id rather than comparing it against a list of
        suspicious words, so it has no gap: an unresolved template token,
        "unknown", "n/a", "12345", "CONTACT_ID_HERE", a sentence the AI wrote,
        and anything else a bot can invent all fail loudly on your first test
        call rather than quietly returning a stranger's quote.

        It also declines to answer for a contact who has exchanged no message
        in the last 24 hours. Treat that as a speed bump rather than a lock: it
        counts messages your business sent as well as ones it received, so a
        campaign send puts every recipient inside the window for a day, and a
        public form submission can refresh it too.

        After changing the wiring, call this endpoint once and confirm you get
        back a quote you recognise, for the person you are actually talking to.

        ## What it answers

        Does an approved quote exist for this customer, what does it total, and
        is it still valid. That is the whole surface. Line items, notes, terms,
        the estimate's public link, signature and payment details, and cost or
        margin are all deliberately absent.

        **There is no title or description, on purpose.** A quote's title is
        free text your team types, and teams put the customer in it: names,
        addresses, email addresses, gate codes. Under the mis-wiring described
        above the response is about the wrong person, and a title would be by
        far the most revealing thing in it, so the quote is identified by its
        number instead. Your customer already knows what they asked you to
        quote for; the bot does not need to tell them.

        Quotes are returned newest first, with any approved one first of all,
        up to five. A quote that is still a draft, or that was declined,
        expired or already turned into an invoice, is not returned at all.

        ## What it refuses

        - Any parameter other than `contactId`, including `email`, `phone`,
          `name` and `address`. This endpoint will not look a person up by
          anything a caller can say. Sending one is a `400`, not a silent
          ignore, so a wrong integration is visible immediately.
        - `contactId` sent more than once.
        - A `contactId` that is not a bare CRM id, including one with stray
          spaces or quotes around it.

        ## About the 404

        An unknown contact, a contact belonging to a different location, a
        deleted contact and a contact with no live conversation all return a
        byte-identical `404`: same status, same headers, same body. That is
        deliberate, so that a key which may only read quotes does not answer
        differently depending on who you ask about.

        The response does not distinguish them. Response TIMING can, by a small
        and non-enumerable margin, because looking up conversations only
        happens once a contact id turns out to belong to this location. Contact
        ids are long random strings, so that cannot be used to find anyone; at
        most it confirms an id somebody already has.

        A customer who IS mid-conversation but has no quote is a `200` with an
        empty list, which is how you tell "no quote yet" from "something is
        wrong with the wiring".

        Requires the `booking-estimates:read` scope. This is not a general
        estimates permission and does not grant one.

        For Standard v2 and OAuth, `meta.truncated` is always present. It is true when
        the scan of the contact's newest estimates or the result limit stopped the answer.
        No cursor continues it, because approved quotes sort first in memory.
      parameters:
        - name: contactId
          in: query
          required: true
          description: |
            The CRM contact id for this conversation, wired from your bot
            platform's source field variable. The only parameter this endpoint
            accepts.
          schema:
            type: string
      responses:
        "200":
          description: |
            The customer's bookable quotes. An empty list means the customer is
            known and mid-conversation but has nothing quoted.
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
            X-RateLimit-Limit:
              $ref: "#/components/headers/X-RateLimit-Limit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/X-RateLimit-Remaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/X-RateLimit-Reset"
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: array
                    items: { $ref: "#/components/schemas/BookingEstimate" }
                  meta:
                    type: object
                    properties:
                      total:
                        type: integer
                        description: How many quotes this response carries.
        "400":
          description: |
            The request did not carry a usable contact id. See the wiring note
            above; the message names the fix.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              examples:
                mis_wired:
                  value:
                    error:
                      code: "VALIDATION_ERROR"
                      message: "contactId is not a CRM contact id. Wire it from the source field variable carrying this CRM contact id, not from a value the bot collects during the conversation."
                other_lookup_key:
                  value:
                    error:
                      code: "VALIDATION_ERROR"
                      message: "contactId is the only parameter this endpoint accepts. It will not look a person up by name, phone, email or address, because those are things a caller can say."
        "401": { $ref: "#/components/responses/Unauthorized" }
        "403": { $ref: "#/components/responses/Forbidden" }
        "404":
          description: |
            One answer for every reason this contact cannot be read here.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: "NOT_FOUND"
                  message: "No estimate is available for this conversation"
        "429": { $ref: "#/components/responses/RateLimited" }

  # =========================================================================
  # ADD-ON ROUTES (EXTENSION SEAM)
  #
  # An installed add-on can contribute its own routes under /api/v1/ext.
  # This spec cannot enumerate them: they are not part of the base product and
  # the add-on may not edit this file. So the seam and its envelope are
  # documented here once, and GET /api/v1/ext reports what a given install
  # actually exposes, derived from the same registry that serves the traffic.
  #
  # With no add-on installed, /api/v1/ext returns an empty list and every path
  # under it returns 404.
  # =========================================================================
  /api/v1/ext:
    get:
      operationId: listExtensionRoutes
      tags: [Add-on routes]
      summary: List the routes contributed by installed add-ons
      description: |
        Returns every route an installed add-on has contributed, with the scope
        each one requires and whether the calling key holds it.

        This is the authoritative list for a given install. Add-on endpoints are
        not described in this spec because the CRM does not know them at build
        time; they are described here, at runtime, by the same registry the
        router dispatches on.

        Routes the calling key cannot reach are still listed, with
        `granted: false`, so an integrator can tell an operator which permission
        to tick on the API key. That is why this endpoint requires only a valid
        key and no particular scope: a key with no scopes at all, and a test-mode
        key, both see the same inventory.

        Only routes the CRM will actually serve are listed, at the path they are
        served on: a `path` from this listing can be called as it is written.
        An add-on route the CRM refuses, because its declaration collides with
        another, names a method this API does not mount, or asks for something
        a contributed route may not have, is absent here as well as `404`
        there. `meta.refused` counts those, so a short list is never a silent
        one.

        Returns an empty list on an install with no add-ons.
      responses:
        "200":
          description: The contributed routes
          headers:
            X-API-Version:
              $ref: "#/components/headers/X-API-Version"
            X-RateLimit-Limit:
              $ref: "#/components/headers/X-RateLimit-Limit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/X-RateLimit-Remaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/X-RateLimit-Reset"
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/ExtensionRoute"
                  meta:
                    type: object
                    properties:
                      total:
                        type: integer
                        description: Routes listed, which is the number this install will serve.
                      refused:
                        type: integer
                        description: |
                          Add-on routes this install is NOT serving because their
                          declaration was rejected. Normally `0`. A non-zero value
                          means the list above is short: the reasons are in the
                          operator's Convex logs, and the add-on's author needs
                          them, because the affected routes return `404`.
        "401":
          $ref: "#/components/responses/Unauthorized"
        "429":
          $ref: "#/components/responses/RateLimited"

  /api/v1/ext/{namespace}/{path}:
    parameters:
      - name: namespace
        in: path
        required: true
        description: The add-on's namespace, as returned by `GET /api/v1/ext`.
        schema:
          type: string
      - name: path
        in: path
        required: true
        description: |
          The route path within that namespace, as returned by `GET /api/v1/ext`.
          Matched exactly: a declared route never claims the paths beneath it.
        schema:
          type: string
    get:
      operationId: callExtensionRouteGet
      tags: [Add-on routes]
      summary: Call a contributed read endpoint
      description: |
        Authentication, scopes, rate limiting and the response envelope are
        identical to every other endpoint in this spec. The add-on decides only
        the shape of `data`.

        **Scope.** Each contributed route requires its own scope, listed by
        `GET /api/v1/ext`. Scopes an add-on contributes appear on the create-key
        form in the CRM alongside the built-in ones.

        **Rate limits.** The usual 120 reads / 30 writes per minute per key, in a
        bucket private to that add-on and that endpoint, and private to the
        sub-account when the key is agency-scoped.

        **Errors.** The documented error codes, unchanged. Two statuses are
        specific to this surface: `502` means the add-on's own handler failed and
        `504` means it did not answer in time. Neither indicates a problem with
        the CRM or with any other endpoint, and neither carries detail about the
        failure, which is recorded in your Convex logs instead.

        **What an add-on can put in an error body.** Exactly one thing: the
        `message` on a `400`, `403`, `404`, `409` or `422` the handler chose to
        return, capped at 500 characters. Every other error body on this surface
        is written by the CRM and never carries text the add-on wrote. In
        particular, an add-on whose handler THROWS produces a fixed body: a
        thrown error carries file paths, stack frames and whatever data was in
        scope, so none of it is relayed. If a caller needs to be told what was
        wrong with their request, the add-on returns that message rather than
        throwing it.

        However an add-on fails, the failure is reported against its own
        endpoint. A `500` on this surface always means the CRM, never the
        add-on.
      responses:
        "200":
          $ref: "#/components/responses/ExtensionRouteResult"
        "400":
          $ref: "#/components/responses/ValidationError"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/RateLimited"
        "502":
          $ref: "#/components/responses/ExtensionHandlerFailed"
        "504":
          $ref: "#/components/responses/ExtensionHandlerTimeout"
    post:
      operationId: callExtensionRoutePost
      tags: [Add-on routes]
      summary: Call a contributed write endpoint
      description: |
        As the GET above. Requires `Content-Type: application/json`; the body is
        capped at 256 KB. The cap is applied to the bytes actually received, so
        it holds for a chunked request that sends no `Content-Length` as well as
        for one that declares its size. Over the cap is a `413`.

        A path that exists only as a `GET` returns `404` for a `POST`, and the
        reverse, so a key holding only the read scope can never reach a write
        handler.
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              description: Defined by the add-on. See `GET /api/v1/ext`.
              additionalProperties: true
      responses:
        "200":
          $ref: "#/components/responses/ExtensionRouteResult"
        "201":
          $ref: "#/components/responses/ExtensionRouteResult"
        "400":
          $ref: "#/components/responses/ValidationError"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "413":
          $ref: "#/components/responses/ValidationError"
        "415":
          $ref: "#/components/responses/ValidationError"
        "429":
          $ref: "#/components/responses/RateLimited"
        "502":
          $ref: "#/components/responses/ExtensionHandlerFailed"
        "504":
          $ref: "#/components/responses/ExtensionHandlerTimeout"

  # =========================================================================
  # VERIFIED CUSTOMER APPOINTMENTS
  #
  # The surface a booking assistant uses to handle ONE caller's own booking.
  # Every endpoint here is POST, including the reads: the identifiers are
  # personal data, and a GET puts a customer's email and phone in the URL,
  # which is where request logs, proxy logs and browser history keep things.
  # =========================================================================
  /api/v1/booking/appointments:
    post:
      x-seedly-oauth-scope: "appointments:read"
      x-seedly-standard-scope: "appointments:read"
      x-seedly-resource-restrictions: {"oauth":["verified_customer"],"standard":["verified_customer"]}
      operationId: lookupVerifiedAppointments
      tags: [Verified appointments]
      summary: Look up one verified customer's appointments
      description: |
        Returns the appointments belonging to a single customer who has proved
        who they are, and nothing else. Never a roster, never another customer.

        **Scope.** `booking-appointments:read`.

        **Identifying the customer.** Send either the CRM contact id, or TWO
        matching identifiers from `email`, `phone` and `lastName`. A last name
        alone is never enough, because two customers sharing a surname is an
        ordinary Tuesday. Both identifiers must belong to the SAME contact
        record.

        **Phone numbers must be E.164.** Normalisation strips non-digits and
        prefixes `+`; it does NOT infer a country code, so `(555) 010-0001`
        becomes `+5550100001` and will not match a stored `+15550100001`.

        **Email is matched exactly, including case**, the same rule
        `GET /api/v1/contacts?email=` uses.

        **Read `meta.hasMore`.** The list is capped at 20. A homeowner never
        hits that; a commercial customer on a recurring route will. Never turn a
        capped list into "you have 20 visits".

        **`partOfSeries: true` means both write endpoints WILL refuse**, and an
        operator is notified instead. Handle it before offering, not after being
        turned down.

        ⚠️ This returns the customer's full history, including cancelled and past
        appointments. If you are about to cancel or move something, use
        `/actionable` instead: an assistant handed the whole history has been
        observed picking a cancelled record out of it.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                contactId: { type: string, description: CRM contact id }
                email: { type: string }
                phone: { type: string, description: E.164 }
                lastName: { type: string }
            examples:
              byContactId:
                summary: By contact id
                value: { contactId: "k57abc..." }
              byPair:
                summary: By two matching identifiers
                value: { email: "jo@example.com", phone: "+15555550123" }
      responses:
        "200":
          description: The customer's appointments, newest-relevant first
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { $ref: "#/components/schemas/VerifiedAppointment" }
                  meta:
                    type: object
                    properties:
                      total: { type: integer }
                      hasMore:
                        type: boolean
                        description: True when the 20-item cap was reached.
        "400":
          description: |
            The request never described a legal identification (no contact id and
            fewer than two identifiers, or a lone last name). Safe to report: it
            is a statement about the request shape, made before any record is read.
          $ref: "#/components/responses/ValidationError"
        "401": { $ref: "#/components/responses/Unauthorized" }
        "403": { $ref: "#/components/responses/Forbidden" }
        "404":
          description: |
            No match. **Deliberately identical** for: an unknown contact, one
            identifier right and the other wrong, two identifiers naming
            DIFFERENT customers, a contact in another tenant, a soft-deleted
            contact, an appointment id belonging to somebody else, and a verified
            customer with nothing booked.

            That sameness is the point. "The email is right, the phone is wrong"
            confirms the email, and confirming an email one request at a time is
            how a customer list is enumerated through a surface that never
            returns one. Do not try to give the caller a more specific reason.
          $ref: "#/components/responses/NotFound"
        "429": { $ref: "#/components/responses/RateLimited" }

  /api/v1/booking/appointments/actionable:
    post:
      x-seedly-oauth-scope: "appointments:read"
      x-seedly-standard-scope: "appointments:read"
      x-seedly-resource-restrictions: {"oauth":["verified_customer"],"standard":["verified_customer"]}
      operationId: lookupActionableAppointments
      tags: [Verified appointments]
      summary: Look up only what that customer can still act on
      description: |
        The same verification as the lookup above, filtered to the appointments
        the customer can still cancel or move. Cancelled, past and recurring
        occurrences are excluded, because those are exactly what the write
        endpoints refuse.

        **Scope.** `booking-appointments:read`. Same scope as the full lookup,
        because it returns strictly less.

        **Use this before a cancel or a reschedule.** An assistant given the full
        history has been observed reading seven records, six of them cancelled,
        telling the customer the correct upcoming time, and then passing a
        cancelled id to the write endpoint. The write refused correctly and the
        assistant relayed that refusal to the customer as "your appointment
        cannot be moved", which was false.

        **The shape is fixed, not conditional.** `appointment` and `appointments`
        are both always present. `appointment` is non-null ONLY when exactly one
        appointment is actionable, which is the case you may act on without
        asking. When several are actionable it is null on purpose and
        `meta.ambiguous` is true: ask the customer which time they mean, by the
        human-readable `label`, before calling a write endpoint.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                contactId: { type: string }
                email: { type: string }
                phone: { type: string, description: E.164 }
                lastName: { type: string }
      responses:
        "200":
          description: The actionable set. May be empty.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      appointment:
                        allOf: [{ $ref: "#/components/schemas/VerifiedAppointment" }]
                        nullable: true
                        description: The single actionable appointment, or null when there are zero or several.
                      appointments:
                        type: array
                        items: { $ref: "#/components/schemas/VerifiedAppointment" }
                  meta:
                    type: object
                    properties:
                      total: { type: integer }
                      ambiguous:
                        type: boolean
                        description: True when more than one appointment is actionable. Ask the customer to choose.
              example:
                data:
                  appointment:
                    id: "j57abc..."
                    title: "Softener install"
                    startTime: 1789059600000
                    endTime: 1789061400000
                    timezone: "America/New_York"
                    localDate: "2026-09-10"
                    label: "Thursday, September 10, 2026 at 1:00 PM EDT"
                    status: "scheduled"
                    canCancel: true
                    canReschedule: true
                    partOfSeries: false
                  appointments: []
                meta: { total: 1, ambiguous: false }
        "400": { $ref: "#/components/responses/ValidationError" }
        "401": { $ref: "#/components/responses/Unauthorized" }
        "403": { $ref: "#/components/responses/Forbidden" }
        "404": { $ref: "#/components/responses/NotFound" }
        "429": { $ref: "#/components/responses/RateLimited" }

  /api/v1/booking/appointments/confirm-sms:
    post:
      x-seedly-oauth-scope: "messages:send"
      x-seedly-resource-restrictions: {"oauth":["integration_owned_booking"]}
      operationId: requestOAuthBookingConfirmation
      tags: [Calendars]
      summary: Request the configured text confirmation for an app-owned booking
      description: |
        OAuth only; requires `messages:send`. The appointment must have been
        created by this application in the authorized location and still be upcoming
        and active. Requires an active contact with a current phone and enabled
        calendar SMS confirmations. Accepts no arbitrary recipient or message.
        Automatic bookings return status=calendar_rules and replayed=true without
        scheduling another text. Requested bookings queue at most one confirmation.
        Consent/DND, quiet hours and sending rules apply. Success acknowledges the
        request, not delivery. Repeated requests return replayed=true without another job.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              required: [appointmentId]
              properties:
                appointmentId: { type: string }
      responses:
        '200':
          description: Confirmation request accepted or previously requested
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: object
                    required: [appointmentId, status, replayed]
                    properties:
                      appointmentId: { type: string }
                      status: { type: string, enum: [requested, calendar_rules] }
                      replayed: { type: boolean }
        '400':
          description: Invalid request, unavailable booking or disabled confirmation
        '401': { $ref: '#/components/responses/Unauthorized' }
        '403': { $ref: '#/components/responses/Forbidden' }
        '429': { $ref: '#/components/responses/RateLimited' }

  /api/v1/booking/appointments/cancel:
    post:
      x-seedly-oauth-scope: "appointments:write"
      x-seedly-standard-scope: "appointments:write"
      x-seedly-resource-restrictions: {"oauth":["verified_customer"],"standard":["verified_customer"]}
      operationId: cancelVerifiedAppointment
      tags: [Verified appointments]
      summary: Cancel one verified customer's appointment
      description: |
        Cancels ONE appointment belonging to the verified customer, and frees the
        time it was holding, including the hold on a connected Google Calendar.

        **Scope.** `booking-appointments:write`.

        **`confirm: true` is required.** An assistant that mishears "no, don't
        cancel" should fail the schema rather than the customer.

        **Idempotent.** Cancelling an already-cancelled appointment returns 200
        with `alreadyCancelled: true` rather than an error, so a retry after a
        timeout is safe. Do not report that to a customer as a failure.

        **A recurring occurrence is refused** with a 400, and the sub-account's
        admins are notified so a person can decide. "Cancel my appointment"
        against a weekly service might mean this Thursday or the whole
        arrangement, and guessing either way is wrong in a way nobody notices
        until it costs money.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [appointmentId, confirm]
              properties:
                contactId: { type: string }
                email: { type: string }
                phone: { type: string }
                lastName: { type: string }
                appointmentId: { type: string }
                confirm: { type: boolean, enum: [true] }
                reason: { type: string }
      responses:
        "200":
          description: Cancelled, or already was
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id: { type: string }
                      status: { type: string, example: cancelled }
                      alreadyCancelled: { type: boolean }
        "400": { $ref: "#/components/responses/ValidationError" }
        "401": { $ref: "#/components/responses/Unauthorized" }
        "403": { $ref: "#/components/responses/Forbidden" }
        "404": { $ref: "#/components/responses/NotFound" }
        "429": { $ref: "#/components/responses/RateLimited" }

  /api/v1/booking/appointments/reschedule:
    post:
      x-seedly-oauth-scope: "appointments:write"
      x-seedly-standard-scope: "appointments:write"
      x-seedly-resource-restrictions: {"oauth":["verified_customer"],"standard":["verified_customer"]}
      operationId: rescheduleVerifiedAppointment
      tags: [Verified appointments]
      summary: Move one verified customer's appointment
      description: |
        Moves ONE appointment belonging to the verified customer to a slot that
        availability offered. The slot is revalidated server-side, so a time
        taken since you read it is refused rather than double-booked, and the old
        slot is released.

        **Scope.** `booking-appointments:write`.

        **Take the slot verbatim** from the availability answer: the epoch
        `startTime` / `endTime` pair, not the ISO strings and not a reconstructed
        time. The fields are named `newStartTime` / `newEndTime` so you cannot
        send the slot object wholesale and have it silently mean the old booking.

        **Refused with a 400** when the slot is taken, when the calendar does not
        allow customer reschedules, when the appointment has already started, and
        when it belongs to a recurring series.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [appointmentId, newStartTime, newEndTime]
              properties:
                contactId: { type: string }
                email: { type: string }
                phone: { type: string }
                lastName: { type: string }
                appointmentId: { type: string }
                newStartTime: { type: integer, description: Unix ms, taken verbatim from availability }
                newEndTime: { type: integer, description: Unix ms }
      responses:
        "200":
          description: Moved
          content:
            application/json:
              schema:
                type: object
                properties:
                  data: { $ref: "#/components/schemas/VerifiedAppointment" }
        "400": { $ref: "#/components/responses/ValidationError" }
        "401": { $ref: "#/components/responses/Unauthorized" }
        "403": { $ref: "#/components/responses/Forbidden" }
        "404": { $ref: "#/components/responses/NotFound" }
        "429": { $ref: "#/components/responses/RateLimited" }

# =============================================================================
# COMPONENTS
# =============================================================================
  /api/v1/calls:
    get:
      x-seedly-oauth-scope: "call-history:read"
      x-seedly-standard-scope: "call-history:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Call Library]
      summary: List call history
      description: >-
        Explicitly approved location-wide OAuth and Standard v2 only; legacy keys and record-restricted grants are denied.
        Requires contacts:read plus call-history:read. Recording reads additionally require calls:recordings:read.
        Transcript reads additionally require calls:transcripts:read and calls:recordings:read.
        Tenant, active contact, parent call and retention checks run before data is returned, with transactional access audits.
        Private notes are returned only by call detail under call_logs view authority. Provider credentials, provider URLs and raw storage IDs are never returned.
        Pages may be empty after eligibility filtering; continue with meta.nextCursor while meta.hasMore is true.
      parameters:
        - name: limit
          in: query
          schema: { type: integer, minimum: 1, maximum: 50, default: 25 }
        - name: cursor
          in: query
          description: Opaque cursor bound to principal, location, resource and source.
          schema: { type: string, maxLength: 8192 }
      responses:
        '200':
          description: Audited, authorized call library response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CallHistoryList'
        '400':
          description: Invalid query, cursor or response size constraint
        '403':
          description: Missing, stale or unsupported permission grant
        '404':
          description: Record unavailable, expired or inaccessible

  /api/v1/calls/{id}:
    get:
      x-seedly-oauth-scope: "call-history:read"
      x-seedly-standard-scope: "call-history:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Call Library]
      summary: Read call history detail
      description: >-
        Explicitly approved location-wide OAuth and Standard v2 only; legacy keys and record-restricted grants are denied.
        Requires contacts:read plus call-history:read. Recording reads additionally require calls:recordings:read.
        Transcript reads additionally require calls:transcripts:read and calls:recordings:read.
        Tenant, active contact, parent call and retention checks run before data is returned, with transactional access audits.
        Private notes are returned only by call detail under call_logs view authority. Provider credentials, provider URLs and raw storage IDs are never returned.
      parameters:
        - name: id
          in: path
          required: true
          schema: { type: string, minLength: 1, maxLength: 256 }
      responses:
        '200':
          description: Audited, authorized call library response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CallHistoryResponse'
        '400':
          description: Invalid query, cursor or response size constraint
        '403':
          description: Missing, stale or unsupported permission grant
        '404':
          description: Record unavailable, expired or inaccessible

    patch:
      x-seedly-oauth-scope: "call-history:write"
      x-seedly-standard-scope: "call-history:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Call Library]
      summary: Update private call notes
      description: >-
        Requires call-history:write, call-history:read and contacts:read with location-wide approval.
        Native permissions are call_logs view, conversations update and contacts view. Only notes may be changed.
        No call facts, dispositions, workflow enrollment or consent/DNC settings are changed. Native inbox summary refresh is retained.
        Idempotency replay rechecks live authority and the retained parent call/contact before returning a receipt.
      parameters:
        - name: id
          in: path
          required: true
          schema: {type: string}
        - name: Idempotency-Key
          in: header
          required: true
          schema: {type: string, minLength: 8, maxLength: 128, pattern: '^[A-Za-z0-9._:-]+$'}
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              required: [notes]
              properties:
                notes: {type: string, maxLength: 16000}
      responses:
        "200":
          description: Durable receipt without note content
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: object
                    required: [id, updated]
                    properties:
                      id: {type: string}
                      updated: {type: boolean, const: true}
        "400":
          description: Invalid payload or missing request key
        "403":
          description: Missing or revoked permission
        "404":
          description: Call or parent contact unavailable
        "409":
          description: Request key reused for different data

    delete:
      x-seedly-oauth-scope: "calls:delete"
      x-seedly-standard-scope: "calls:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "deleteCallsId"
      tags: ["Calls"]
      summary: "DELETE /api/v1/calls/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Also requires call-history:read and contacts:read. Permanently deletes the call and its recordings, stored audio, transcripts, grades and lead extractions."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/call-dispositions:
    get:
      x-seedly-oauth-scope: "call-history:read"
      x-seedly-standard-scope: "call-history:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Call Library]
      summary: Read configured call dispositions
      description: >-
        Explicitly approved location-wide OAuth and Standard v2 only; legacy keys and record-restricted grants are denied.
        Requires contacts:read plus call-history:read. Recording reads additionally require calls:recordings:read.
        Transcript reads additionally require calls:transcripts:read and calls:recordings:read.
        Tenant, active contact, parent call and retention checks run before data is returned, with transactional access audits.
        Private notes are returned only by call detail under call_logs view authority. Provider credentials, provider URLs and raw storage IDs are never returned.
      responses:
        '200':
          description: Audited, authorized call library response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CallDispositionResponse'
        '400':
          description: Invalid query, cursor or response size constraint
        '403':
          description: Missing, stale or unsupported permission grant
        '404':
          description: Record unavailable, expired or inaccessible

    put:
      x-seedly-oauth-scope: "call-settings:write"
      x-seedly-standard-scope: "call-settings:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "putCallDispositions"
      tags: ["Calls"]
      summary: "PUT /api/v1/call-dispositions"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Also requires call-history:read and contacts:read. Replaces the outcome list by ID. Native fields such as the do-not-call flag are kept, and an outcome flagged for do-not-call cannot be dropped. A location that inherits its call settings from the brand is refused with brand_call_settings_inherited; give it its own settings in the app first."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["dispositions"],"properties":{"dispositions":{"type":"array","maxItems":50,"items":{"type":"object","additionalProperties":false,"required":["id","label"],"properties":{"id":{"type":"string"},"label":{"type":"string"},"color":{"type":"string"}}}}}}}}}
  /api/v1/call-recordings:
    get:
      x-seedly-oauth-scope: "calls:recordings:read"
      x-seedly-standard-scope: "calls:recordings:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Call Library]
      summary: List recording metadata
      description: >-
        Explicitly approved location-wide OAuth and Standard v2 only; legacy keys and record-restricted grants are denied.
        Requires contacts:read plus call-history:read. Recording reads additionally require calls:recordings:read.
        Transcript reads additionally require calls:transcripts:read and calls:recordings:read.
        Tenant, active contact, parent call and retention checks run before data is returned, with transactional access audits.
        Private notes are returned only by call detail under call_logs view authority. Provider credentials, provider URLs and raw storage IDs are never returned.
        Pages may be empty after eligibility filtering; continue with meta.nextCursor while meta.hasMore is true.
      parameters:
        - name: limit
          in: query
          schema: { type: integer, minimum: 1, maximum: 50, default: 25 }
        - name: cursor
          in: query
          description: Opaque cursor bound to principal, location, resource and source.
          schema: { type: string, maxLength: 8192 }
        - name: source
          in: query
          schema: { type: string, enum: [native, app], default: native }
      responses:
        '200':
          description: Audited, authorized call library response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CallRecordingList'
        '400':
          description: Invalid query, cursor or response size constraint
        '403':
          description: Missing, stale or unsupported permission grant
        '404':
          description: Record unavailable, expired or inaccessible

  /api/v1/call-recordings/{id}:
    get:
      x-seedly-oauth-scope: "calls:recordings:read"
      x-seedly-standard-scope: "calls:recordings:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Call Library]
      summary: Read recording metadata
      description: >-
        Explicitly approved location-wide OAuth and Standard v2 only; legacy keys and record-restricted grants are denied.
        Requires contacts:read plus call-history:read. Recording reads additionally require calls:recordings:read.
        Transcript reads additionally require calls:transcripts:read and calls:recordings:read.
        Tenant, active contact, parent call and retention checks run before data is returned, with transactional access audits.
        Private notes are returned only by call detail under call_logs view authority. Provider credentials, provider URLs and raw storage IDs are never returned.
      parameters:
        - name: id
          in: path
          required: true
          schema: { type: string, minLength: 1, maxLength: 256 }
      responses:
        '200':
          description: Audited, authorized call library response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CallRecordingResponse'
        '400':
          description: Invalid query, cursor or response size constraint
        '403':
          description: Missing, stale or unsupported permission grant
        '404':
          description: Record unavailable, expired or inaccessible

    delete:
      x-seedly-oauth-scope: "calls:recordings:delete"
      x-seedly-standard-scope: "calls:recordings:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "deleteCallRecordingsId"
      tags: ["Calls"]
      summary: "DELETE /api/v1/call-recordings/{id}"
      description: "Requires explicit location-wide OAuth or Standard v2 operation approval. Legacy keys, CloseBot and own/team/selected grants are unsupported. Existing Standard snapshots do not acquire new routes.  Requires Idempotency-Key. Retrying with the same key returns the original receipt without repeating the effect. Also requires calls:recordings:read, call-history:read and contacts:read. Permanently removes stored audio and its transcripts, grades and lead extractions. The call stays."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses: {"200":{"description":"Safe bounded projection or durable minimal receipt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}},"400":{"description":"Unsupported input, invalid cursor, or bounded operation exceeded."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current operation or dependency approval."},"404":{"description":"Record unavailable."},"409":{"description":"Idempotency or state conflict."},"429":{"description":"Rate limit exceeded."}}
  /api/v1/call-recordings/{id}/playback:
    get:
      x-seedly-oauth-scope: "calls:recordings:read"
      x-seedly-standard-scope: "calls:recordings:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Call Library]
      summary: Request audited recording playback
      description: >-
        Explicitly approved location-wide OAuth and Standard v2 only; legacy keys and record-restricted grants are denied.
        Requires contacts:read plus call-history:read. Recording reads additionally require calls:recordings:read.
        Transcript reads additionally require calls:transcripts:read and calls:recordings:read.
        Tenant, active contact, parent call and retention checks run before data is returned, with transactional access audits.
        Private notes are returned only by call detail under call_logs view authority. Provider credentials, provider URLs and raw storage IDs are never returned.
        Playback returns authenticated audio bytes, never a storage URL. Each fetch rechecks authority and is audited. Maximum 64 MiB; byte ranges are unsupported (416).
      parameters:
        - name: id
          in: path
          required: true
          schema: { type: string, minLength: 1, maxLength: 256 }
      responses:
        '200':
          description: Audited, authorized call library response
          content:
            audio/mpeg:
              schema: { type: string, format: binary }
            audio/mp3:
              schema: { type: string, format: binary }
            audio/wav:
              schema: { type: string, format: binary }
            audio/x-wav:
              schema: { type: string, format: binary }
            audio/mp4:
              schema: { type: string, format: binary }
            audio/ogg:
              schema: { type: string, format: binary }
            audio/webm:
              schema: { type: string, format: binary }
        '400':
          description: Invalid query, cursor or response size constraint
        '403':
          description: Missing, stale or unsupported permission grant
        '404':
          description: Record unavailable, expired or inaccessible

        '413':
          description: Audio exceeds 64 MiB
        '415':
          description: Stored content is not an allowed audio format
        '416':
          description: Range requests are unsupported; fetch the complete file

  /api/v1/call-transcripts:
    get:
      x-seedly-oauth-scope: "calls:transcripts:read"
      x-seedly-standard-scope: "calls:transcripts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Call Library]
      summary: List transcript metadata
      description: >-
        Explicitly approved location-wide OAuth and Standard v2 only; legacy keys and record-restricted grants are denied.
        Requires contacts:read plus call-history:read. Recording reads additionally require calls:recordings:read.
        Transcript reads additionally require calls:transcripts:read and calls:recordings:read.
        Tenant, active contact, parent call and retention checks run before data is returned, with transactional access audits.
        Private notes are returned only by call detail under call_logs view authority. Provider credentials, provider URLs and raw storage IDs are never returned.
        Pages may be empty after eligibility filtering; continue with meta.nextCursor while meta.hasMore is true.
      parameters:
        - name: limit
          in: query
          schema: { type: integer, minimum: 1, maximum: 50, default: 25 }
        - name: cursor
          in: query
          description: Opaque cursor bound to principal, location, resource and source.
          schema: { type: string, maxLength: 8192 }
        - name: source
          in: query
          schema: { type: string, enum: [native, app], default: native }
      responses:
        '200':
          description: Audited, authorized call library response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CallTranscriptList'
        '400':
          description: Invalid query, cursor or response size constraint
        '403':
          description: Missing, stale or unsupported permission grant
        '404':
          description: Record unavailable, expired or inaccessible

  /api/v1/call-transcripts/{id}:
    get:
      x-seedly-oauth-scope: "calls:transcripts:read"
      x-seedly-standard-scope: "calls:transcripts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Call Library]
      summary: Read audited transcript content
      description: >-
        Explicitly approved location-wide OAuth and Standard v2 only; legacy keys and record-restricted grants are denied.
        Requires contacts:read plus call-history:read. Recording reads additionally require calls:recordings:read.
        Transcript reads additionally require calls:transcripts:read and calls:recordings:read.
        Tenant, active contact, parent call and retention checks run before data is returned, with transactional access audits.
        Private notes are returned only by call detail under call_logs view authority. Provider credentials, provider URLs and raw storage IDs are never returned.
      parameters:
        - name: id
          in: path
          required: true
          schema: { type: string, minLength: 1, maxLength: 256 }
      responses:
        '200':
          description: Audited, authorized call library response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CallTranscriptResponse'
        '400':
          description: Invalid query, cursor or response size constraint
        '403':
          description: Missing, stale or unsupported permission grant
        '404':
          description: Record unavailable, expired or inaccessible

  /api/v1/conversations/{id}/contact:
    get:
      x-seedly-oauth-scope: "conversations:read"
      x-seedly-standard-scope: "conversations:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getConversationContact"
      summary: "Read relationship revision"
      tags: ["Conversations"]
      description: "Location-wide conversations:read and independently approved contacts:read. Returns the live shared-email relationship revision for optimistic writes. Unsupported channel/privacy/queued-message associations fail closed."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}]
      responses: {"200": {"description": "Relationship and epoch-ms revision.", "content": {"application/json": {"schema": {"type": "object", "properties": {"data": {"type": "object", "required": ["id", "contactId", "updatedAt"], "properties": {"id": {"type": "string"}, "contactId": {"type": "string"}, "updatedAt": {"type": "number"}}}}}}}}, "403": {"description": "Unsupported relationship or insufficient live authority."}}
    patch:
      x-seedly-oauth-scope: "conversations:write"
      x-seedly-standard-scope: "conversations:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "relinkConversationContact"
      tags: ["Conversations"]
      summary: "relinkConversationContact"
      description: "Location-wide OAuth or Standard v2 with explicit route approval and contacts:read. Legacy keys and restricted record grants are unsupported. This increment supports shared email/email-transactional conversations only, without native-call, Meta-identity, public-chat session, Gmail mailbox or channel-thread bindings. Relink validates at most100 terminal messages and 512 KiB of stored message data and rejects automation-log associations. Merge source must be read; incoming unread activity blocks continuation until explicitly read and resumed. Each message batch (at most 25 rows and 256 KiB plus one document) rechecks the persisted credential, effective token scope ceiling and pinned live source/target/contact. Cancellation preserves committed moves, unread counters and repaired previews, and releases locks. Only the same credential can read/control the job; operators with all-record conversation update authority can stop it in the sidebar even after credential revocation. Resume verifies the current token ceiling. Shared contact/company parents are rechecked. Merge finalization repairs message reports, deduplicates exact-case tags, migrates auto-response conversation references, removes typing indicators and logs activity. Status/control bodies never disclose message content. Completed merge retries return current job status; changed live parents fail closed. Read GET /conversations/:id/contact to obtain epoch-millisecond updatedAt. Initial relink requires expectedUpdatedAt; merge requires expectedSourceUpdatedAt and expectedTargetUpdatedAt. Stale initial revisions return409; original receipt retries do not reapply or compare the obsolete initial revision."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "minLength": 8, "maxLength": 128}}]
      responses: {"200": {"description": "Receipt or current merge job state.", "content": {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"type": "object", "required": ["id", "contactId", "updated"], "properties": {"id": {"type": "string"}, "contactId": {"type": "string"}, "updated": {"const": true}}}}}}}}, "400": {"description": "Invalid input or relink exceeds100 messages."}, "401": {"description": "Invalid credential."}, "403": {"description": "Missing authority or unsupported private/channel association."}, "409": {"description": "Changed relationship, unread source or conflicting request key."}, "429": {"description": "Rate limit exceeded."}}
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "required": ["contactId", "expectedUpdatedAt"], "properties": {"contactId": {"type": "string"}, "expectedUpdatedAt": {"type": "integer", "minimum": 0}}}}}}
  /api/v1/conversations/{id}/merge:
    post:
      x-seedly-oauth-scope: "conversations:merge"
      x-seedly-standard-scope: "conversations:merge"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "startConversationMerge"
      tags: ["Conversations"]
      summary: "startConversationMerge"
      description: "Location-wide OAuth or Standard v2 with explicit route approval and contacts:read. Legacy keys and restricted record grants are unsupported. This increment supports shared email/email-transactional conversations only, without native-call, Meta-identity, public-chat session, Gmail mailbox or channel-thread bindings. Relink validates at most100 terminal messages and 512 KiB of stored message data and rejects automation-log associations. Merge source must be read; incoming unread activity blocks continuation until explicitly read and resumed. Each message batch (at most 25 rows and 256 KiB plus one document) rechecks the persisted credential, effective token scope ceiling and pinned live source/target/contact. Cancellation preserves committed moves, unread counters and repaired previews, and releases locks. Only the same credential can read/control the job; operators with all-record conversation update authority can stop it in the sidebar even after credential revocation. Resume verifies the current token ceiling. Shared contact/company parents are rechecked. Merge finalization repairs message reports, deduplicates exact-case tags, migrates auto-response conversation references, removes typing indicators and logs activity. Status/control bodies never disclose message content. Completed merge retries return current job status; changed live parents fail closed. Read GET /conversations/:id/contact to obtain epoch-millisecond updatedAt. Initial relink requires expectedUpdatedAt; merge requires expectedSourceUpdatedAt and expectedTargetUpdatedAt. Stale initial revisions return409; original receipt retries do not reapply or compare the obsolete initial revision."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "minLength": 8, "maxLength": 128}}]
      responses: {"200": {"description": "Receipt or current merge job state.", "content": {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"type": "object", "additionalProperties": false, "required": ["id", "sourceId", "targetId", "status", "messagesMoved", "partial", "updatedAt"], "properties": {"id": {"type": "string"}, "sourceId": {"type": "string"}, "targetId": {"type": "string"}, "status": {"enum": ["running", "blocked", "cancelled", "complete"]}, "messagesMoved": {"type": "integer"}, "partial": {"type": "boolean"}, "updatedAt": {"type": "number"}}}}}}}}, "400": {"description": "Invalid input or relink exceeds100 messages."}, "401": {"description": "Invalid credential."}, "403": {"description": "Missing authority or unsupported private/channel association."}, "409": {"description": "Changed relationship, unread source or conflicting request key."}, "429": {"description": "Rate limit exceeded."}}
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "required": ["targetId", "expectedSourceUpdatedAt", "expectedTargetUpdatedAt"], "properties": {"targetId": {"type": "string"}, "expectedSourceUpdatedAt": {"type": "integer", "minimum": 0}, "expectedTargetUpdatedAt": {"type": "integer", "minimum": 0}}}}}}
  /api/v1/conversation-merge-jobs/{id}:
    get:
      x-seedly-oauth-scope: "conversations:merge"
      x-seedly-standard-scope: "conversations:merge"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "getConversationMergeJob"
      tags: ["Conversations"]
      summary: "getConversationMergeJob"
      description: "Location-wide OAuth or Standard v2 with explicit route approval and contacts:read. Legacy keys and restricted record grants are unsupported. This increment supports shared email/email-transactional conversations only, without native-call, Meta-identity, public-chat session, Gmail mailbox or channel-thread bindings. Relink validates at most100 terminal messages and 512 KiB of stored message data and rejects automation-log associations. Merge source must be read; incoming unread activity blocks continuation until explicitly read and resumed. Each message batch (at most 25 rows and 256 KiB plus one document) rechecks the persisted credential, effective token scope ceiling and pinned live source/target/contact. Cancellation preserves committed moves, unread counters and repaired previews, and releases locks. Only the same credential can read/control the job; operators with all-record conversation update authority can stop it in the sidebar even after credential revocation. Resume verifies the current token ceiling. Shared contact/company parents are rechecked. Merge finalization repairs message reports, deduplicates exact-case tags, migrates auto-response conversation references, removes typing indicators and logs activity. Status/control bodies never disclose message content. Completed merge retries return current job status; changed live parents fail closed. Read GET /conversations/:id/contact to obtain epoch-millisecond updatedAt. Initial relink requires expectedUpdatedAt; merge requires expectedSourceUpdatedAt and expectedTargetUpdatedAt. Stale initial revisions return409; original receipt retries do not reapply or compare the obsolete initial revision."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}]
      responses: {"200": {"description": "Receipt or current merge job state.", "content": {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"type": "object", "additionalProperties": false, "required": ["id", "sourceId", "targetId", "status", "messagesMoved", "partial", "updatedAt"], "properties": {"id": {"type": "string"}, "sourceId": {"type": "string"}, "targetId": {"type": "string"}, "status": {"enum": ["running", "blocked", "cancelled", "complete"]}, "messagesMoved": {"type": "integer"}, "partial": {"type": "boolean"}, "updatedAt": {"type": "number"}}}}}}}}, "400": {"description": "Invalid input or relink exceeds100 messages."}, "401": {"description": "Invalid credential."}, "403": {"description": "Missing authority or unsupported private/channel association."}, "409": {"description": "Changed relationship, unread source or conflicting request key."}, "429": {"description": "Rate limit exceeded."}}
  /api/v1/conversation-merge-jobs/{id}/control:
    post:
      x-seedly-oauth-scope: "conversations:merge"
      x-seedly-standard-scope: "conversations:merge"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "controlConversationMergeJob"
      tags: ["Conversations"]
      summary: "controlConversationMergeJob"
      description: "Location-wide OAuth or Standard v2 with explicit route approval and contacts:read. Legacy keys and restricted record grants are unsupported. This increment supports shared email/email-transactional conversations only, without native-call, Meta-identity, public-chat session, Gmail mailbox or channel-thread bindings. Relink validates at most100 terminal messages and 512 KiB of stored message data and rejects automation-log associations. Merge source must be read; incoming unread activity blocks continuation until explicitly read and resumed. Each message batch (at most 25 rows and 256 KiB plus one document) rechecks the persisted credential, effective token scope ceiling and pinned live source/target/contact. Cancellation preserves committed moves, unread counters and repaired previews, and releases locks. Only the same credential can read/control the job; operators with all-record conversation update authority can stop it in the sidebar even after credential revocation. Resume verifies the current token ceiling. Shared contact/company parents are rechecked. Merge finalization repairs message reports, deduplicates exact-case tags, migrates auto-response conversation references, removes typing indicators and logs activity. Status/control bodies never disclose message content. Completed merge retries return current job status; changed live parents fail closed. Read GET /conversations/:id/contact to obtain epoch-millisecond updatedAt. Initial relink requires expectedUpdatedAt; merge requires expectedSourceUpdatedAt and expectedTargetUpdatedAt. Stale initial revisions return409; original receipt retries do not reapply or compare the obsolete initial revision."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "minLength": 8, "maxLength": 128}}]
      responses: {"200": {"description": "Receipt or current merge job state.", "content": {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"type": "object", "additionalProperties": false, "required": ["id", "sourceId", "targetId", "status", "messagesMoved", "partial", "updatedAt"], "properties": {"id": {"type": "string"}, "sourceId": {"type": "string"}, "targetId": {"type": "string"}, "status": {"enum": ["running", "blocked", "cancelled", "complete"]}, "messagesMoved": {"type": "integer"}, "partial": {"type": "boolean"}, "updatedAt": {"type": "number"}}}}}}}}, "400": {"description": "Invalid input or relink exceeds100 messages."}, "401": {"description": "Invalid credential."}, "403": {"description": "Missing authority or unsupported private/channel association."}, "409": {"description": "Changed relationship, unread source or conflicting request key."}, "429": {"description": "Rate limit exceeded."}}
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "required": ["action"], "properties": {"action": {"enum": ["cancel", "resume"]}}}}}}

  /api/v1/conversations/{id}/scheduled-messages:
    get:
      x-seedly-oauth-scope: "conversations:read"
      x-seedly-standard-scope: "conversations:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listConversationScheduledMessages
      tags: [Conversations]
      summary: "List scheduled messages"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval plus contacts:read. Legacy API keys and own, team or selected record grants are denied. Returns queued messages on one conversation. Gmail messages and internal notes are not returned."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "messages:manage"
      x-seedly-standard-scope: "messages:manage"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: scheduleConversationMessage
      tags: [Conversations]
      summary: "Schedule a customer message"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval plus contacts:read. Legacy API keys and own, team or selected record grants are denied. Requires messages:manage. Queues a native scheduled message that appears in the inbox and can be cancelled there. SMS, email, Messenger, Instagram, social DM and live chat threads are supported. Social DM and live chat follow the thread and take no toAddress or channel change. A live chat visitor sees the message only when it fires. Gmail is refused here: use the OAuth Gmail operations. The send runs through the native channel action when it fires, so suppression, consent, DND, quiet hours, rate limits and billing are enforced at that time. The original credential, including an OAuth token ceiling, is reauthorized when the send fires; if authority was lost the message is marked failed and nothing is sent. Merge fields are not substituted by this path, so a body containing a merge chip is refused. Undeclared email class is decided at send time from the reply window. Attachments need an email thread and files:read, reference up to 20 attachment files in this location or linked to this contact, and cannot be combined with toAddress. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["bodyText","scheduledFor"],"properties":{"bodyText":{"type":"string","minLength":1},"bodyHtml":{"type":"string"},"channel":{"type":"string","enum":["sms","email","email-transactional","messenger","instagram","social_dm","live_chat"]},"toAddress":{"type":"string"},"subject":{"type":"string"},"scheduledFor":{"type":"integer","description":"Epoch milliseconds, at most one year ahead."},"fileIds":{"type":"array","maxItems":20,"uniqueItems":true,"items":{"type":"string"}},"messageType":{"enum":["marketing","transactional"]},"listId":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/conversations/{id}/transcript:
    get:
      x-seedly-oauth-scope: "conversations:read"
      x-seedly-standard-scope: "conversations:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getConversationTranscript
      tags: [Conversations]
      summary: "Read a conversation transcript"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Also requires contacts:read. Returns one thread oldest first, up to 100 entries a page, so a long thread is read by following the cursor. Queued messages are not included. Gmail messages show covered text and privateChannel unless they are in the OAuth user's own mailbox; a Standard key sees them covered."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/conversations/{id}/scheduled-gmail-messages:
    get:
      x-seedly-oauth-scope: "messages:gmail"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: listScheduledGmailMessages
      tags: [Conversations]
      summary: "List your scheduled Gmail messages"
      description: "Location-wide only and OAuth only: a Standard key has no form of this operation. Legacy API keys and own, team or selected record grants are denied. Also requires contacts:read. Returns only the messages the approving user queued on this conversation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "messages:gmail"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: scheduleGmailMessage
      tags: [Conversations]
      summary: "Schedule a Gmail message"
      description: "Location-wide only and OAuth only: a Standard key has no form of this operation. Legacy API keys and own, team or selected record grants are denied. Also requires contacts:read. Sends from the approving user's own connected Gmail on a Gmail or email thread. With several connected mailboxes the user's primary mailbox is used. When the send fires, the original grant, that user and that mailbox are all rechecked; if any is gone the message is marked failed and nothing is sent. Attachments need files:read, reference attachment files in this location or linked to this contact, and cannot be combined with toAddress. Merge fields are not substituted, so a body containing a merge chip is refused. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["bodyText","scheduledFor"],"properties":{"bodyText":{"type":"string","minLength":1},"bodyHtml":{"type":"string"},"toAddress":{"type":"string"},"subject":{"type":"string"},"scheduledFor":{"type":"integer","description":"Epoch milliseconds, at most one year ahead."},"fileIds":{"type":"array","maxItems":20,"uniqueItems":true,"items":{"type":"string"}},"messageType":{"enum":["marketing","transactional"]}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/scheduled-gmail-messages/{id}:
    delete:
      x-seedly-oauth-scope: "messages:gmail"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: cancelScheduledGmailMessage
      tags: [Conversations]
      summary: "Cancel a scheduled Gmail message"
      description: "Location-wide only and OAuth only: a Standard key has no form of this operation. Legacy API keys and own, team or selected record grants are denied. Also requires contacts:read. Only the user who queued the message can cancel it this way. A message that already fired cannot be cancelled. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/conversation-messages/{id}/gmail-retry:
    post:
      x-seedly-oauth-scope: "messages:gmail"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      operationId: retryGmailMessage
      tags: [Conversations]
      summary: "Retry a failed Gmail message"
      description: "Location-wide only and OAuth only: a Standard key has no form of this operation. Legacy API keys and own, team or selected record grants are denied. Also requires contacts:read. Requeues a failed or bounced Gmail message from the approving user's own Gmail. The message must be one they sent or one their mailbox holds. Every native send screen runs again. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaign-folders:
    get:
      x-seedly-oauth-scope: "campaigns:read"
      x-seedly-standard-scope: "campaigns:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listCampaignFolders
      tags: [Campaigns]
      summary: "List campaign folders"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Returns up to 200 folders."
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"type":"object","properties":{"hasMore":{"type":"boolean"},"cursor":{"type":"null"},"truncated":{"type":"boolean","description":"True when more than 200 exist. No cursor continues this list."}}}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "campaigns:write"
      x-seedly-standard-scope: "campaigns:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createCampaignFolder
      tags: [Campaigns]
      summary: "Create a campaign folder"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. parentId nests it under a folder in this location. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"},"parentId":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaign-folders/{id}:
    patch:
      x-seedly-oauth-scope: "campaigns:write"
      x-seedly-standard-scope: "campaigns:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateCampaignFolder
      tags: [Campaigns]
      summary: "Rename a campaign folder"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Changes the name only. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "campaigns:delete"
      x-seedly-standard-scope: "campaigns:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteCampaignFolder
      tags: [Campaigns]
      summary: "Delete a campaign folder"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Campaigns and child folders move to the top level. A folder holding more than 200 of either is refused with 409 and nothing changes. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaign-categories:
    get:
      x-seedly-oauth-scope: "campaigns:read"
      x-seedly-standard-scope: "campaigns:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listCampaignCategories
      tags: [Campaigns]
      summary: "List email categories"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Returns up to 200 categories, the lists contacts set preferences on."
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"type":"object","properties":{"hasMore":{"type":"boolean"},"cursor":{"type":"null"},"truncated":{"type":"boolean","description":"True when more than 200 exist. No cursor continues this list."}}}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "campaigns:write"
      x-seedly-standard-scope: "campaigns:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createCampaignCategory
      tags: [Campaigns]
      summary: "Create an email category"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. A new category is never transactional. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"},"description":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaign-categories/{id}:
    patch:
      x-seedly-oauth-scope: "campaigns:write"
      x-seedly-standard-scope: "campaigns:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateCampaignCategory
      tags: [Campaigns]
      summary: "Update an email category"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Changes the name or description. The transactional setting is not editable here. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string"},"description":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "campaigns:delete"
      x-seedly-standard-scope: "campaigns:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteCampaignCategory
      tags: [Campaigns]
      summary: "Delete an email category"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Refused with 409 when any contact preference or campaign refers to it, because contact preferences are opt-out records and are never removed through the API. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaigns/{id}/folder:
    post:
      x-seedly-oauth-scope: "campaigns:write"
      x-seedly-standard-scope: "campaigns:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: moveCampaignToFolder
      tags: [Campaigns]
      summary: "Move a campaign to a folder"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. folderId null moves it to the top level. An SMS campaign also requires campaigns:sms. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["folderId"],"properties":{"folderId":{"type":["string","null"]}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaigns/{id}/archive:
    post:
      x-seedly-oauth-scope: "campaigns:write"
      x-seedly-standard-scope: "campaigns:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: archiveCampaign
      tags: [Campaigns]
      summary: "Archive or unarchive a campaign"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Sets the archived flag only. An SMS campaign also requires campaigns:sms. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["archived"],"properties":{"archived":{"type":"boolean"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaigns/{id}/brand-style:
    post:
      x-seedly-oauth-scope: "campaigns:write"
      x-seedly-standard-scope: "campaigns:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: applyCampaignBrandStyle
      tags: [Campaigns]
      summary: "Apply a brand style to a draft"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Draft campaigns only, for a broadcast or every sequence step. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["brandStyleId"],"properties":{"brandStyleId":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/template-campaigns:
    post:
      x-seedly-oauth-scope: "campaigns:write"
      x-seedly-standard-scope: "campaigns:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createCampaignFromTemplate
      tags: [Campaigns]
      summary: "Create a draft from a template"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Creates an email draft. templateId also requires templates:read. Nothing is sent. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name","type"],"properties":{"name":{"type":"string"},"type":{"enum":["broadcast","sequence"]},"templateId":{"type":"string"},"folderId":{"type":"string"},"brandStyleId":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/contact-campaigns:
    post:
      x-seedly-oauth-scope: "campaigns:write"
      x-seedly-standard-scope: "campaigns:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createCampaignFromContacts
      tags: [Campaigns]
      summary: "Create a draft for named contacts"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Also requires contacts:read; an SMS draft requires campaigns:sms. Names up to 1000 live contacts in this location. Nothing is sent, and every consent and suppression screen runs for each contact when the draft is sent. A send needs a listId. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name","contactIds"],"properties":{"name":{"type":"string"},"channel":{"enum":["email","sms"]},"contactIds":{"type":"array","minItems":1,"maxItems":1000,"uniqueItems":true,"items":{"type":"string"}},"listId":{"type":"string"},"bodyText":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaigns/{id}/non-opener-resend:
    post:
      x-seedly-oauth-scope: "campaigns:write"
      x-seedly-standard-scope: "campaigns:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createNonOpenerResend
      tags: [Campaigns]
      summary: "Create a non-opener resend draft"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Creates a draft of a sent email campaign for recipients who have not opened it after hoursWindow, at most 2160. It starts no delivery: send or schedule it through those routes, which need their own authority and run every consent and suppression screen per recipient. Only one resend can exist per campaign. While gathering is true the audience is still being built and sending is refused. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["newSubject","hoursWindow"],"properties":{"newSubject":{"type":"string"},"hoursWindow":{"type":"integer","minimum":1,"maximum":2160}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaigns/{id}/ab-winner:
    post:
      x-seedly-oauth-scope: "campaigns:lifecycle"
      x-seedly-standard-scope: "campaigns:lifecycle"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: declareCampaignAbWinner
      tags: [Campaigns]
      summary: "Declare an A/B winner"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Records a named variant of a finished A/B campaign as the winner and sets its subject and body on the campaign. Refused while a campaign is scheduled or sending. Nothing is sent. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["winnerVariant"],"properties":{"winnerVariant":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaigns/{id}/analytics-jobs:
    post:
      x-seedly-oauth-scope: "campaigns:read"
      x-seedly-standard-scope: "campaigns:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: startCampaignAnalyticsJob
      tags: [Campaigns]
      summary: "Start a campaign analytics job"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. kind ab counts recipients per variant with significance, non_openers counts recipients who have not opened after hoursWindow. Reads every recipient in bounded pages, rechecking authority each page, so a large campaign is exact rather than sampled. Results are totals and hold no contact ids. Past recipient retention the job reports recipientsPurged instead of zeros. An SMS campaign also requires campaigns:sms. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["kind"],"properties":{"kind":{"enum":["ab","non_openers"]},"hoursWindow":{"type":"integer","minimum":1,"maximum":2160}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaign-analytics-jobs/{id}:
    get:
      x-seedly-oauth-scope: "campaigns:read"
      x-seedly-standard-scope: "campaigns:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getCampaignAnalyticsJob
      tags: [Campaigns]
      summary: "Read a campaign analytics job"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Only the credential that started the job can read it. results is present once status is complete. Jobs expire after 7 days."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaign-analytics-jobs/{id}/control:
    post:
      x-seedly-oauth-scope: "campaigns:read"
      x-seedly-standard-scope: "campaigns:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: controlCampaignAnalyticsJob
      tags: [Campaigns]
      summary: "Cancel or resume an analytics job"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Resuming continues a blocked job under the caller's current token ceiling. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["action"],"properties":{"action":{"enum":["cancel","resume"]}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflow-folders:
    get:
      x-seedly-oauth-scope: "workflows:read"
      x-seedly-standard-scope: "workflows:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listWorkflowFolders
      tags: [Workflows]
      summary: "List workflow folders"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Returns up to 200 folders."
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"type":"object","properties":{"hasMore":{"type":"boolean"},"cursor":{"type":"null"},"truncated":{"type":"boolean","description":"True when more than 200 exist. No cursor continues this list."}}}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "workflows:write"
      x-seedly-standard-scope: "workflows:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createWorkflowFolder
      tags: [Workflows]
      summary: "Create a workflow folder"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. parentId nests it under a folder in this location. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"},"parentId":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflow-folders/{id}:
    patch:
      x-seedly-oauth-scope: "workflows:write"
      x-seedly-standard-scope: "workflows:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateWorkflowFolder
      tags: [Workflows]
      summary: "Rename a workflow folder"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Changes the name only. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "workflows:delete"
      x-seedly-standard-scope: "workflows:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteWorkflowFolder
      tags: [Workflows]
      summary: "Delete a workflow folder"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Workflows and child folders move to the top level. A folder holding more than can be moved in one call is refused with 409 and nothing changes. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflows/{id}/folder:
    post:
      x-seedly-oauth-scope: "workflows:write"
      x-seedly-standard-scope: "workflows:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: moveWorkflowToFolder
      tags: [Workflows]
      summary: "Move a workflow to a folder"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. folderId null moves it to the top level. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["folderId"],"properties":{"folderId":{"type":["string","null"]}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflows/{id}/duplicate:
    post:
      x-seedly-oauth-scope: "workflows:write"
      x-seedly-standard-scope: "workflows:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: duplicateWorkflow
      tags: [Workflows]
      summary: "Duplicate a workflow"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Also requires workflows:read. Creates a draft copy. Stored credentials are not copied and must be entered again, and nothing runs until the copy is published. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflow-templates:
    get:
      x-seedly-oauth-scope: "workflows:read"
      x-seedly-standard-scope: "workflows:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listWorkflowTemplates
      tags: [Workflows]
      summary: "List workflow templates"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Returns global templates and this agency's templates, without their graphs. A page can be short when other agencies' rows are filtered; follow the cursor."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}},{"name":"category","in":"query","schema":{"type":"string","maxLength":64}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflow-templates/{id}/workflows:
    post:
      x-seedly-oauth-scope: "workflows:write"
      x-seedly-standard-scope: "workflows:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createWorkflowFromTemplate
      tags: [Workflows]
      summary: "Create a draft from a template"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Creates a draft. A template never carries credentials, and records from another location are marked for reselection. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string"},"description":{"type":"string"},"folderId":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflows/{id}/export:
    get:
      x-seedly-oauth-scope: "workflows:read"
      x-seedly-standard-scope: "workflows:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: exportWorkflow
      tags: [Workflows]
      summary: "Export a workflow"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Returns the draft definition as portable JSON. Credentials, webhook addresses and run state are left out."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflow-imports:
    post:
      x-seedly-oauth-scope: "workflows:write"
      x-seedly-standard-scope: "workflows:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: importWorkflow
      tags: [Workflows]
      summary: "Import a workflow"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Creates a draft from exported JSON. A record from another location is refused and must be repointed first, and sender defaults and run state are refused. Nothing runs until it is published, and publishing checks every step. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name","dag"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"triggerType":{"type":"string"},"triggerConfig":{"type":"object"},"dag":{"type":"object"},"settings":{"type":"object"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflows/{id}/settings:
    patch:
      x-seedly-oauth-scope: "workflows:write"
      x-seedly-standard-scope: "workflows:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateWorkflowSettings
      tags: [Workflows]
      summary: "Update workflow settings"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Sets communicationTimeWindow, timezoneMode, allowMultipleOpportunities, markConversationsRead, exitOnCustomer or exitOnUnsubscribe. These apply to live runs immediately, so a workflow that has been published also requires workflows:publish. exitOnUnsubscribe cannot be turned off here. allowReEntry and stopOnResponse stay on the definition route. Sender defaults are not available through the API. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"timezoneMode":{"enum":["account","contact"]},"allowMultipleOpportunities":{"type":"boolean"},"markConversationsRead":{"type":"boolean"},"exitOnCustomer":{"type":"boolean"},"exitOnUnsubscribe":{"enum":[true]},"communicationTimeWindow":{"type":"object"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflows/{id}/node-enrollments:
    get:
      x-seedly-oauth-scope: "workflows:read"
      x-seedly-standard-scope: "workflows:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listWorkflowNodeEnrollments
      tags: [Workflows]
      summary: "Count live runs per step"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Counts running enrollments per step for one page of runs. Sum across the cursor for the whole workflow."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":500}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflows/{id}/node-history:
    get:
      x-seedly-oauth-scope: "workflows:read"
      x-seedly-standard-scope: "workflows:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listWorkflowNodeHistory
      tags: [Workflows]
      summary: "Read history for one step"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Requires nodeId. Returns the outcome of one step across recent runs, newest first: status, duration and time. Step input, output and error text are never returned. A page can end early at its byte limit; follow the cursor."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}},{"name":"nodeId","in":"query","schema":{"type":"string","maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflows/{id}/ab-results:
    get:
      x-seedly-oauth-scope: "workflows:read"
      x-seedly-standard-scope: "workflows:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getWorkflowAbResults
      tags: [Workflows]
      summary: "Read A/B results for a step"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Requires nodeId. Returns totals per variant and the declared winner, with no contact ids. isApproximate is true when the step holds more rows than one read covers."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"nodeId","in":"query","schema":{"type":"string","maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflows/{id}/ab-winner:
    post:
      x-seedly-oauth-scope: "workflows:write"
      x-seedly-standard-scope: "workflows:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: declareWorkflowAbWinner
      tags: [Workflows]
      summary: "Declare a winner for an A/B step"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Sets the winner on the draft graph of an ab-split step. A workflow that is not a draft also requires workflows:publish, and keeps running its published version until it is published again. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["nodeId","winnerIndex"],"properties":{"nodeId":{"type":"string"},"winnerIndex":{"type":"integer","minimum":0}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/scheduled-messages/{id}:
    delete:
      x-seedly-oauth-scope: "messages:manage"
      x-seedly-standard-scope: "messages:manage"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: cancelScheduledMessage
      tags: [Conversations]
      summary: "Cancel a scheduled message"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval plus contacts:read. Legacy API keys and own, team or selected record grants are denied. Requires messages:manage. Removes the queued message, its scheduler entry and attachment rows through the native cancellation command. A message that already fired cannot be cancelled. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/conversation-messages/{id}/retry:
    post:
      x-seedly-oauth-scope: "messages:manage"
      x-seedly-standard-scope: "messages:manage"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: retryConversationMessage
      tags: [Conversations]
      summary: "Retry a failed message"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval plus contacts:read. Legacy API keys and own, team or selected record grants are denied. Requires messages:manage. Requeues one failed or bounced outbound message through the native channel action, keeping its original email class and list, so every send screen runs again. Gmail and community DM messages are refused, and so are test credentials. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/conversation-messages/{id}/attachments:
    get:
      x-seedly-oauth-scope: "conversations:read"
      x-seedly-standard-scope: "conversations:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listConversationMessageAttachments
      tags: [Conversations]
      summary: "List message attachments"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval plus contacts:read. Legacy API keys and own, team or selected record grants are denied. Metadata only. No storage URL is ever returned. Gmail messages are not available because Gmail is personal to one user."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/message-attachments/{id}/content:
    get:
      x-seedly-oauth-scope: "conversations:read"
      x-seedly-standard-scope: "conversations:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: downloadMessageAttachment
      tags: [Conversations]
      summary: "Download a message attachment"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval plus contacts:read. Legacy API keys and own, team or selected record grants are denied. Returns authenticated bytes as a forced download, at most 10 MiB. No reusable storage URL is issued."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Attachment bytes."
          content: {"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/conversation-bulk-jobs:
    post:
      x-seedly-oauth-scope: "conversations:write"
      x-seedly-standard-scope: "conversations:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: startConversationBulkJob
      tags: [Conversations]
      summary: "Start a conversation bulk job"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval plus contacts:read. Legacy API keys and own, team or selected record grants are denied. Requires conversations:write. Applies one inbox state change to at most 500 distinct conversations in a durable job. Each batch of 25 rechecks the credential and each conversation; records that are gone or outside this location are counted as skipped. If authority is lost the job is blocked and can be resumed by the same credential. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["action","conversationIds"],"properties":{"action":{"enum":["mark_read","mark_unread","archive","unarchive","star","unstar"]},"conversationIds":{"type":"array","minItems":1,"maxItems":500,"uniqueItems":true,"items":{"type":"string"}}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/conversation-bulk-jobs/{id}:
    get:
      x-seedly-oauth-scope: "conversations:read"
      x-seedly-standard-scope: "conversations:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getConversationBulkJob
      tags: [Conversations]
      summary: "Read a conversation bulk job"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval plus contacts:read. Legacy API keys and own, team or selected record grants are denied. Only the credential that started the job can read it. Reports total, processed, applied and skipped counts."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/conversation-bulk-jobs/{id}/control:
    post:
      x-seedly-oauth-scope: "conversations:write"
      x-seedly-standard-scope: "conversations:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: controlConversationBulkJob
      tags: [Conversations]
      summary: "Cancel or resume a conversation bulk job"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval plus contacts:read. Legacy API keys and own, team or selected record grants are denied. Cancel keeps changes already applied. Resume applies to a blocked job and adopts the current token ceiling. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["action"],"properties":{"action":{"enum":["cancel","resume"]}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/conversations/{id}/relink-jobs:
    post:
      x-seedly-oauth-scope: "conversations:write"
      x-seedly-standard-scope: "conversations:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: startConversationRelinkJob
      tags: [Conversations]
      summary: "Start a large conversation relink"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval plus contacts:read. Legacy API keys and own, team or selected record grants are denied. Requires conversations:write. Same eligibility rules as PATCH /api/v1/conversations/{id}/contact, for threads above its 100 message bound. The thread is locked, every message is checked in bounded batches that recheck authority, and the contact changes only after the full scan passes. A blocked job changes nothing; cancel releases the lock. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["contactId","expectedUpdatedAt"],"properties":{"contactId":{"type":"string"},"expectedUpdatedAt":{"type":"integer"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/conversation-relink-jobs/{id}:
    get:
      x-seedly-oauth-scope: "conversations:read"
      x-seedly-standard-scope: "conversations:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getConversationRelinkJob
      tags: [Conversations]
      summary: "Read a conversation relink job"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval plus contacts:read. Legacy API keys and own, team or selected record grants are denied. Only the credential that started the job can read it."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/conversation-relink-jobs/{id}/control:
    post:
      x-seedly-oauth-scope: "conversations:write"
      x-seedly-standard-scope: "conversations:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: controlConversationRelinkJob
      tags: [Conversations]
      summary: "Cancel or resume a conversation relink job"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval plus contacts:read. Legacy API keys and own, team or selected record grants are denied. Resume restarts the scan of a blocked job under the current token ceiling. Cancel releases the conversation lock. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["action"],"properties":{"action":{"enum":["cancel","resume"]}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaigns/{id}/recipients:
    get:
      x-seedly-oauth-scope: "campaigns:read"
      x-seedly-standard-scope: "campaigns:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listCampaignRecipients
      tags: [Campaigns]
      summary: "List campaign recipients"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. SMS campaigns additionally require campaigns:sms. Requires campaigns:read and contacts:read. Returns recipient state and contact ids at most 100 per page, never contact details or provider metadata. Contacts that were deleted return a null contactId. Past retention, meta.recipientsPurged is true and no rows exist."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}},{"name":"status","in":"query","schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaigns/{id}/analytics:
    get:
      x-seedly-oauth-scope: "campaigns:read"
      x-seedly-standard-scope: "campaigns:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getCampaignAnalytics
      tags: [Campaigns]
      summary: "Read campaign analytics"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. SMS campaigns additionally require campaigns:sms. Requires campaigns:read. Returns exact recipient counters where the campaign has them, otherwise the stored counters with isApproximate true, plus per-step counts for sequences. No per-recipient data."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaigns/{id}/steps:
    get:
      x-seedly-oauth-scope: "campaigns:read"
      x-seedly-standard-scope: "campaigns:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listCampaignSteps
      tags: [Campaigns]
      summary: "List sequence steps"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. SMS campaigns additionally require campaigns:sms. Requires campaigns:read. Step bodies are returned only by the single-step read."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "campaigns:write"
      x-seedly-standard-scope: "campaigns:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createCampaignStep
      tags: [Campaigns]
      summary: "Add a sequence step"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. SMS campaigns additionally require campaigns:sms. Requires campaigns:write. Draft sequences only, at most 100 steps. HTML is sanitized with the email profile. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"subject":{"type":"string"},"bodyHtml":{"type":"string"},"bodyText":{"type":"string"},"preheader":{"type":"string"},"delayMinutes":{"type":"integer","minimum":0}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaigns/{id}/steps/reorder:
    post:
      x-seedly-oauth-scope: "campaigns:write"
      x-seedly-standard-scope: "campaigns:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: reorderCampaignSteps
      tags: [Campaigns]
      summary: "Reorder sequence steps"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. SMS campaigns additionally require campaigns:sms. Requires campaigns:write. stepIds must name every step exactly once. Draft sequences only. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["stepIds"],"properties":{"stepIds":{"type":"array","maxItems":100,"items":{"type":"string"}}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaign-steps/{id}:
    get:
      x-seedly-oauth-scope: "campaigns:read"
      x-seedly-standard-scope: "campaigns:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getCampaignStep
      tags: [Campaigns]
      summary: "Read a sequence step"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. SMS campaigns additionally require campaigns:sms. Requires campaigns:read."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "campaigns:write"
      x-seedly-standard-scope: "campaigns:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateCampaignStep
      tags: [Campaigns]
      summary: "Update a sequence step"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. SMS campaigns additionally require campaigns:sms. Requires campaigns:write. Draft sequences only. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"subject":{"type":"string"},"bodyHtml":{"type":"string"},"bodyText":{"type":"string"},"preheader":{"type":"string"},"delayMinutes":{"type":"integer","minimum":0}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "campaigns:delete"
      x-seedly-standard-scope: "campaigns:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteCampaignStep
      tags: [Campaigns]
      summary: "Delete a sequence step"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. SMS campaigns additionally require campaigns:sms. Requires campaigns:delete. Draft sequences only; remaining steps are renumbered. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaigns/{id}/cancel-schedule:
    post:
      x-seedly-oauth-scope: "campaigns:lifecycle"
      x-seedly-standard-scope: "campaigns:lifecycle"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: cancelCampaignSchedule
      tags: [Campaigns]
      summary: "Cancel a scheduled campaign"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. SMS campaigns additionally require campaigns:sms. Requires campaigns:lifecycle. Returns the campaign to draft and ends any deferred send authority. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaigns/{id}/pause:
    post:
      x-seedly-oauth-scope: "campaigns:lifecycle"
      x-seedly-standard-scope: "campaigns:lifecycle"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: pauseCampaign
      tags: [Campaigns]
      summary: "Pause a campaign"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. SMS campaigns additionally require campaigns:sms. Requires campaigns:lifecycle. Applies to sending or scheduled campaigns, including ones a person started. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaigns/{id}/resume:
    post:
      x-seedly-oauth-scope: "campaigns:lifecycle"
      x-seedly-standard-scope: "campaigns:lifecycle"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: resumeCampaign
      tags: [Campaigns]
      summary: "Resume a campaign"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. SMS campaigns additionally require campaigns:sms. Requires campaigns:lifecycle. Sending continues under this credential, and each batch rechecks it. Refused for test credentials. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaigns/{id}/retry-failed:
    post:
      x-seedly-oauth-scope: "campaigns:lifecycle"
      x-seedly-standard-scope: "campaigns:lifecycle"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: retryCampaignFailedRecipients
      tags: [Campaigns]
      summary: "Retry failed recipients"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. SMS campaigns additionally require campaigns:sms. Requires campaigns:lifecycle. Requeues failed recipients through the native sender, so every suppression, consent and cap check runs again. A send that may already have been delivered is skipped rather than repeated. Refused for test credentials. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaigns/{id}/start-sequence:
    post:
      x-seedly-oauth-scope: "campaigns:lifecycle"
      x-seedly-standard-scope: "campaigns:lifecycle"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: startCampaignSequence
      tags: [Campaigns]
      summary: "Start an email sequence"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. SMS campaigns additionally require campaigns:sms. Requires campaigns:lifecycle. Draft email or SMS sequences only, with at least one step and a valid list. An SMS sequence needs campaigns:sms, text on every step and marketing consent in its audience. A step that follows up non-openers by SMS also needs campaigns:sms. Each sequence tick rechecks this credential; if authority is lost the campaign pauses. Refused for test credentials. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaigns/{id}/test:
    post:
      x-seedly-oauth-scope: "campaigns:lifecycle"
      x-seedly-standard-scope: "campaigns:lifecycle"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: sendCampaignTest
      tags: [Campaigns]
      summary: "Send a test email"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. SMS campaigns additionally require campaigns:sms. Requires campaigns:lifecycle. Delivers one test to the credential owner or an active member of this location, within the native test-send cap. Refused for test credentials. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["testEmail"],"properties":{"testEmail":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaigns/{id}/duplicate:
    post:
      x-seedly-oauth-scope: "campaigns:write"
      x-seedly-standard-scope: "campaigns:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: duplicateCampaign
      tags: [Campaigns]
      summary: "Duplicate a campaign"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. SMS campaigns additionally require campaigns:sms. Requires campaigns:write. Creates a draft copy with sequence steps and zeroed stats; it sends nothing. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/sequence-campaigns:
    post:
      x-seedly-oauth-scope: "campaigns:write"
      x-seedly-standard-scope: "campaigns:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createSequenceCampaign
      tags: [Campaigns]
      summary: "Create a sequence draft"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. SMS campaigns additionally require campaigns:sms. Requires campaigns:write. Creates an email or SMS sequence draft; add steps, then start it. channel sms also requires campaigns:sms. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"},"listId":{"type":"string"},"channel":{"enum":["email","sms"]}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/sms-campaigns:
    post:
      x-seedly-oauth-scope: "campaigns:sms"
      x-seedly-standard-scope: "campaigns:sms"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createSmsCampaign
      tags: [Campaigns]
      summary: "Create an SMS campaign draft"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. SMS campaigns additionally require campaigns:sms. Requires campaigns:sms. The opt-out line is on by default, as it is in the app. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"},"listId":{"type":"string"},"bodyText":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/sms-campaigns/{id}:
    patch:
      x-seedly-oauth-scope: "campaigns:sms"
      x-seedly-standard-scope: "campaigns:sms"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateSmsCampaign
      tags: [Campaigns]
      summary: "Update an SMS campaign draft"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. SMS campaigns additionally require campaigns:sms. Requires campaigns:sms. Drafts only. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string"},"bodyText":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaigns/{id}/send-sms:
    post:
      x-seedly-oauth-scope: "campaigns:sms"
      x-seedly-standard-scope: "campaigns:sms"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: sendSmsCampaign
      tags: [Campaigns]
      summary: "Send an SMS campaign"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. SMS campaigns additionally require campaigns:sms. Requires campaigns:sms. Billable. Marketing SMS consent is checked before starting, and each send runs the native SMS screens. Each batch rechecks this credential. Refused for test credentials. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/campaigns/{id}/schedule-sms:
    post:
      x-seedly-oauth-scope: "campaigns:sms"
      x-seedly-standard-scope: "campaigns:sms"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: scheduleSmsCampaign
      tags: [Campaigns]
      summary: "Schedule an SMS campaign"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. SMS campaigns additionally require campaigns:sms. Requires campaigns:sms. Billable when it fires. The credential is rechecked when the schedule fires. scheduledAt is epoch milliseconds, at most one year ahead. Refused for test credentials. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["scheduledAt"],"properties":{"scheduledAt":{"type":"integer"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflows/{id}/definition:
    get:
      x-seedly-oauth-scope: "workflows:read"
      x-seedly-standard-scope: "workflows:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getWorkflowDefinition
      tags: [Workflows]
      summary: "Read a workflow definition"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Requires workflows:read. Credentials stay redacted and webhook URLs and secrets are never returned. At most 1 MiB."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "workflows:write"
      x-seedly-standard-scope: "workflows:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateWorkflowDefinition
      tags: [Workflows]
      summary: "Edit a workflow definition"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Requires workflows:write, which grants no execution. A live workflow keeps running its published version until someone with workflows:publish publishes the edit. Stored credentials stay bound to their URL, native validation applies. allowReEntry and stopOnResponse reach running executions at once, so they are accepted only on a workflow that was never published. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string"},"description":{"type":"string"},"dag":{"type":"object"},"triggerType":{"type":"string"},"triggerConfig":{"type":"object"},"allowReEntry":{"type":"boolean"},"stopOnResponse":{"type":"boolean"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflow-catalog:
    get:
      x-seedly-oauth-scope: "workflows:read"
      x-seedly-standard-scope: "workflows:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getWorkflowCatalog
      tags: [Workflows]
      summary: "List workflow node and trigger types"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Requires workflows:read. Current node and trigger types with labels."
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflows/{id}/stats:
    get:
      x-seedly-oauth-scope: "workflows:read"
      x-seedly-standard-scope: "workflows:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getWorkflowStats
      tags: [Workflows]
      summary: "Read workflow execution counts"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Requires workflows:read. Counter-backed; available is false when a workflow has no counters yet."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflows/{id}/versions:
    get:
      x-seedly-oauth-scope: "workflows:read"
      x-seedly-standard-scope: "workflows:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listWorkflowVersions
      tags: [Workflows]
      summary: "List workflow versions"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Requires workflows:read. Metadata only. The newest ten versions are kept."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "workflows:write"
      x-seedly-standard-scope: "workflows:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createWorkflowVersion
      tags: [Workflows]
      summary: "Snapshot a workflow version"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Requires workflows:write. Changes nothing that runs. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"note":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflow-versions/{id}:
    get:
      x-seedly-oauth-scope: "workflows:read"
      x-seedly-standard-scope: "workflows:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getWorkflowVersion
      tags: [Workflows]
      summary: "Read a workflow version"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Requires workflows:read. Credentials stay redacted. At most 1 MiB."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflow-versions/{id}/restore:
    post:
      x-seedly-oauth-scope: "workflows:publish"
      x-seedly-standard-scope: "workflows:publish"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: restoreWorkflowVersion
      tags: [Workflows]
      summary: "Restore a workflow version"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Requires workflows:publish because restoring returns the workflow to draft and stops new enrollments. In-flight runs keep their snapshot. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/contacts/{id}/workflow-executions:
    get:
      x-seedly-oauth-scope: "workflows:read"
      x-seedly-standard-scope: "workflows:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listContactWorkflowExecutions
      tags: [Workflows]
      summary: "List workflow runs for a contact"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Requires workflows:read and contacts:read. Run metadata only, never step payloads."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflows/{id}/publish:
    post:
      x-seedly-oauth-scope: "workflows:publish"
      x-seedly-standard-scope: "workflows:publish"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: publishWorkflow
      tags: [Workflows]
      summary: "Publish a workflow"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Requires workflows:publish. Runs native publish validation and creates a version. A publish that would remove live trigger filters is refused until confirmFilterRemoval is true. Only reviewed step types can go live through the API, checked through every add-to-workflow target: payment, invoice, estimate, delete, DND, unenroll, campaign enrollment, webhook, code and other outbound steps are refused. Workflows without a human author cannot use task, manual SMS or manual call steps. Refused for test credentials. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"confirmFilterRemoval":{"type":"boolean"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflows/{id}/pause:
    post:
      x-seedly-oauth-scope: "workflows:publish"
      x-seedly-standard-scope: "workflows:publish"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: pauseWorkflow
      tags: [Workflows]
      summary: "Pause a workflow"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Requires workflows:publish. Active workflows only. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflows/{id}/resume:
    post:
      x-seedly-oauth-scope: "workflows:publish"
      x-seedly-standard-scope: "workflows:publish"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: resumeWorkflow
      tags: [Workflows]
      summary: "Resume a workflow"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Requires workflows:publish. Paused workflows only. The same step-type review as publish runs again, including add-to-workflow targets. Refused for test credentials. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflows/{id}/deactivate:
    post:
      x-seedly-oauth-scope: "workflows:publish"
      x-seedly-standard-scope: "workflows:publish"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deactivateWorkflow
      tags: [Workflows]
      summary: "Deactivate a workflow"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Requires workflows:publish. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflows/{id}/unpublish:
    post:
      x-seedly-oauth-scope: "workflows:publish"
      x-seedly-standard-scope: "workflows:publish"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: unpublishWorkflow
      tags: [Workflows]
      summary: "Unpublish a workflow"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Requires workflows:publish. Returns the workflow to draft; in-flight runs keep their snapshot. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflows/{id}/enrollments:
    post:
      x-seedly-oauth-scope: "workflows:enroll"
      x-seedly-standard-scope: "workflows:enroll"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: enrollWorkflowContact
      tags: [Workflows]
      summary: "Enroll a contact"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Requires workflows:enroll and contacts:read. Starts one run of an active workflow through the native executor, so each step applies its usual consent, suppression and rate rules. The same step-type review as publish runs again, including add-to-workflow targets. Refused for test credentials. The older connected-app enrollment route and workflows:execute are unchanged. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["contactId"],"properties":{"contactId":{"type":"string"},"triggerNodeId":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/workflow-executions/{id}/unenroll:
    post:
      x-seedly-oauth-scope: "workflows:unenroll"
      x-seedly-standard-scope: "workflows:unenroll"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: unenrollWorkflowExecution
      tags: [Workflows]
      summary: "Stop a workflow run"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Requires workflows:unenroll. Stops one running execution and records activity on the contact. Steps already taken are not undone. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/contacts/{id}/consent-status:
    get:
      x-seedly-oauth-scope: "consent:read"
      x-seedly-standard-scope: "consent:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getContactConsentStatus
      tags: [Contacts]
      summary: "Read consent and messaging status"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval plus contacts:read. Legacy API keys and own, team or selected record grants are denied. Requires consent:read. Returns the same per-channel, per-purpose verdicts the senders apply, plus stored consent state. List-level opt-outs are per list and are not included."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/contacts/{id}/consent-history:
    get:
      x-seedly-oauth-scope: "consent:read"
      x-seedly-standard-scope: "consent:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listContactConsentHistory
      tags: [Contacts]
      summary: "List consent history"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval plus contacts:read. Legacy API keys and own, team or selected record grants are denied. Requires consent:read. The evidence trail, newest first, which can include IP address, form URL and disclosure text."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/contacts/{id}/consent:
    post:
      x-seedly-oauth-scope: "consent:manage"
      x-seedly-standard-scope: "consent:manage"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: recordContactConsent
      tags: [Contacts]
      summary: "Record a consent change with evidence"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval plus contacts:read. Legacy API keys and own, team or selected record grants are denied. Requires consent:manage. This is the only consent write in the API: contact writes never change consent. Evidence states method, source and capture time. A grant also needs the disclosure text and applies only where no status was ever recorded. A grant over any opt-out, revocation, marketing opt-out marker, outbound DND or active suppression is refused; those end through the contact's own re-consent. Revocations are always accepted. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["channel","status","evidence"],"properties":{"channel":{"enum":["email","sms","sms_marketing"]},"status":{"enum":["granted","revoked"]},"evidence":{"type":"object","additionalProperties":false,"required":["method","source","capturedAt"],"properties":{"method":{"type":"string"},"source":{"type":"string","maxLength":500},"capturedAt":{"type":"integer","description":"Epoch milliseconds, not in the future."},"disclosureText":{"type":"string","maxLength":5000},"ipAddress":{"type":"string"},"formUrl":{"type":"string"}}}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/contacts/{id}/consent-requests:
    post:
      x-seedly-oauth-scope: "consent:request"
      x-seedly-standard-scope: "consent:request"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: requestContactOptIn
      tags: [Contacts]
      summary: "Record a pending customer opt-in request"
      description: "Requires contacts:read and consent:request with explicit location-wide operation approval. A request records evidence only. It sends no messages and does not change consent or suppressions. Email requires a current subscription; SMS requires an active location-owned sender and distinguishes service from marketing. SMS instructions may be displayed to the customer. An app cannot confirm. Requests expire after seven days. At most 20 new requests per contact per day."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","additionalProperties":false,"required":["channel","purpose","categoryId","evidence"],"properties":{"channel":{"enum":["email"]},"purpose":{"enum":["subscription"]},"categoryId":{"type":"string"},"evidence":{"type":"object","additionalProperties":false,"required":["method","source","capturedAt","disclosureText"],"properties":{"method":{"type":"string","enum":["web_form","verbal","written","text_opt_in"]},"source":{"type":"string","maxLength":500},"capturedAt":{"type":"integer","description":"Epoch milliseconds, not in the future."},"disclosureText":{"type":"string","maxLength":5000},"ipAddress":{"type":"string"},"formUrl":{"type":"string"}}}}},{"type":"object","additionalProperties":false,"required":["channel","purpose","businessSenderId","evidence"],"properties":{"channel":{"enum":["sms"]},"purpose":{"enum":["service","marketing"]},"businessSenderId":{"type":"string"},"evidence":{"type":"object","additionalProperties":false,"required":["method","source","capturedAt","disclosureText"],"properties":{"method":{"type":"string","enum":["web_form","verbal","written","text_opt_in"]},"source":{"type":"string","maxLength":500},"capturedAt":{"type":"integer","description":"Epoch milliseconds, not in the future."},"disclosureText":{"type":"string","maxLength":5000},"ipAddress":{"type":"string"},"formUrl":{"type":"string"}}}}}]}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["id","requestId","status","channel","purpose","expiresAt"],"properties":{"id":{"type":"string"},"requestId":{"type":"string"},"status":{"enum":["pending"]},"channel":{"enum":["email","sms"]},"purpose":{"enum":["service","marketing","subscription"]},"expiresAt":{"type":"string","format":"date-time"},"businessNumber":{"type":"string"},"replyText":{"type":"string"}}}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Conflicting idempotency receipt, stale target or too many fresh requests for this contact.
        '429':
          description: Rate limit exceeded.

  /api/v1/suppression-import-jobs:
    post:
      x-seedly-oauth-scope: "consent:manage"
      x-seedly-standard-scope: "consent:manage"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: startSuppressionImport
      tags: [Consent]
      summary: "Import suppressions"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Also requires contacts:read. Starts a durable job for up to 2000 addresses. Imports only add restrictions: a new row is created, a lifted row is reinstated, and a marketing unsubscribe becomes a hard suppression. Nothing is released, and an imported row can never be released through the API. source says where the list came from and is kept in the audit log. An invalid address is counted in rejected and listed by input position; the rest continue. Each batch rechecks authority, and a job that loses it stops at blocked. Addresses are removed from the job when it ends. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["entries","source"],"properties":{"source":{"type":"string","minLength":1,"maxLength":500},"entries":{"type":"array","minItems":1,"maxItems":2000,"items":{"type":"object","additionalProperties":false,"required":["channel"],"properties":{"channel":{"enum":["email","sms","voice"]},"email":{"type":"string"},"phone":{"type":"string"}}}}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/suppression-import-jobs/{id}:
    get:
      x-seedly-oauth-scope: "consent:read"
      x-seedly-standard-scope: "consent:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getSuppressionImport
      tags: [Consent]
      summary: "Read a suppression import"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Also requires contacts:read. Only the credential that started the job can read it. Returns counts and rejected input positions, never addresses."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/suppression-import-jobs/{id}/control:
    post:
      x-seedly-oauth-scope: "consent:manage"
      x-seedly-standard-scope: "consent:manage"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: controlSuppressionImport
      tags: [Consent]
      summary: "Cancel or resume a suppression import"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Also requires contacts:read. Cancelling stops the job and keeps every restriction already imported. Resuming continues a blocked job under the caller's current token ceiling. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["action"],"properties":{"action":{"enum":["cancel","resume"]}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/suppression-exports:
    post:
      x-seedly-oauth-scope: "suppressions:export"
      x-seedly-standard-scope: "suppressions:export"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: startSuppressionExport
      tags: [Consent]
      summary: "Export the suppression list"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Also requires consent:read and contacts:read. Builds a CSV of standing suppressions in the background. The file holds email addresses and phone numbers, so it is available for a limited time, then deleted. Each chunk rechecks authority, and losing it deletes the output. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/suppression-exports/{id}:
    get:
      x-seedly-oauth-scope: "suppressions:export"
      x-seedly-standard-scope: "suppressions:export"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getSuppressionExport
      tags: [Consent]
      summary: "Read a suppression export"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Also requires consent:read and contacts:read. Only the credential that started the export can read it."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/suppression-exports/{id}/content:
    get:
      x-seedly-oauth-scope: "suppressions:export"
      x-seedly-standard-scope: "suppressions:export"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getSuppressionExportContent
      tags: [Consent]
      summary: "Download a suppression export"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Also requires consent:read and contacts:read. Returns one CSV part at a time; follow the cursor. The first download is recorded in the audit log."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":1}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"object","description":"One CSV part of the export.","required":["contentType","part","csv"],"properties":{"contentType":{"type":"string","const":"text/csv"},"part":{"type":"integer","minimum":0,"description":"Zero-based index of this part."},"csv":{"type":"string","description":"The CSV text of this part. Join the parts in order to rebuild the file."}}},"meta":{"type":"object","required":["limit","hasMore","cursor","truncated"],"properties":{"limit":{"type":"integer","const":1,"description":"Parts returned per call."},"hasMore":{"type":"boolean","description":"True when another part follows. This is the only stop signal."},"cursor":{"type":["string","null"],"description":"Pass as the cursor parameter to read the next part. Null on the last part."},"truncated":{"type":"boolean","description":"True when the job stopped at its 100,000 row limit, so the export is incomplete."}}}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/suppression-exports/{id}/cancel:
    post:
      x-seedly-oauth-scope: "suppressions:export"
      x-seedly-standard-scope: "suppressions:export"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: cancelSuppressionExport
      tags: [Consent]
      summary: "Cancel a suppression export"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Also requires consent:read and contacts:read. Stops the export and deletes its output. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/suppression-exports/{id}/resume:
    post:
      x-seedly-oauth-scope: "suppressions:export"
      x-seedly-standard-scope: "suppressions:export"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: resumeSuppressionExport
      tags: [Consent]
      summary: "Resume a stalled suppression export"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Also requires consent:read and contacts:read. Restarts only a stalled export. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/suppressions:
    get:
      x-seedly-oauth-scope: "consent:read"
      x-seedly-standard-scope: "consent:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listSuppressions
      tags: [Contacts]
      summary: "List active suppressions"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval plus contacts:read. Legacy API keys and own, team or selected record grants are denied. Requires consent:read. Newest first. Filtering lifted rows can leave a page short; continue until hasMore is false."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "consent:manage"
      x-seedly-standard-scope: "consent:manage"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: addSuppression
      tags: [Contacts]
      summary: "Add a suppression"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval plus contacts:read. Legacy API keys and own, team or selected record grants are denied. Requires consent:manage. Adds an email, SMS or voice Do-Not-Call suppression with evidence. An existing row is never rewritten: an active row stays as it is and a lifted row returns with its original reason. The response reports alreadySuppressed, and blocksTransactional is false when the standing row is a marketing unsubscribe, which does not stop transactional email. releasable reports whether the row, as it stands now, can be released: only an email or SMS row an integration inserted, untouched by any other opt-out. A row added again after release cannot be released. Email suppression tied to a contact stops that contact's running workflows, as it does in the app. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["channel","evidence"],"properties":{"channel":{"enum":["email","sms","voice"]},"email":{"type":"string"},"phone":{"type":"string"},"contactId":{"type":"string"},"evidence":{"type":"object","additionalProperties":false,"required":["method","source","capturedAt"],"properties":{"method":{"type":"string"},"source":{"type":"string","maxLength":500},"capturedAt":{"type":"integer","description":"Epoch milliseconds, not in the future."},"disclosureText":{"type":"string","maxLength":5000},"ipAddress":{"type":"string"},"formUrl":{"type":"string"}}}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/suppressions/lookup:
    get:
      x-seedly-oauth-scope: "consent:read"
      x-seedly-standard-scope: "consent:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: lookupSuppression
      tags: [Contacts]
      summary: "Look up a suppression"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval plus contacts:read. Legacy API keys and own, team or selected record grants are denied. Requires consent:read. Exact match on one email or phone. Returns at most 50 rows; truncated is true when more exist."
      parameters: [{"name":"email","in":"query","schema":{"type":"string"}},{"name":"phone","in":"query","schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/suppressions/{id}/release:
    post:
      x-seedly-oauth-scope: "suppressions:release"
      x-seedly-standard-scope: "suppressions:release"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: releaseSuppression
      tags: [Contacts]
      summary: "Release a manual suppression"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval plus contacts:read. Legacy API keys and own, team or selected record grants are denied. Requires suppressions:release and evidence with disclosure text. Only an email or SMS suppression an integration added can be released, and only while no consumer or provider opt-out has landed on it. Every other row is refused, including unsubscribes, keyword opt-outs, complaints, bounces, rows added in the app and voice Do-Not-Call rows. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["evidence"],"properties":{"evidence":{"type":"object","additionalProperties":false,"required":["method","source","capturedAt"],"properties":{"method":{"type":"string"},"source":{"type":"string","maxLength":500},"capturedAt":{"type":"integer","description":"Epoch milliseconds, not in the future."},"disclosureText":{"type":"string","maxLength":5000},"ipAddress":{"type":"string"},"formUrl":{"type":"string"}}}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/live-chat/widget:
    get:
      x-seedly-oauth-scope: "conversations:read"
      x-seedly-standard-scope: "conversations:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getLiveChatWidget
      tags: [Conversations]
      summary: "Read chat widget settings"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Requires conversations:read. Returns configured false when the widget was never set up. No avatar storage reference is returned."
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "live-chat:manage"
      x-seedly-standard-scope: "live-chat:manage"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateLiveChatWidget
      tags: [Conversations]
      summary: "Update chat widget settings"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Requires live-chat:manage. Enabling opens the public visitor endpoints for this location. Avatars are not settable here. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"enabled":{"type":"boolean"},"title":{"type":"string","maxLength":80},"subtitle":{"type":"string","maxLength":160},"position":{"enum":["bottom-right","bottom-left"]},"primaryColor":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$"},"greeting":{"type":"string","maxLength":500},"welcomeMessage":{"type":"string","maxLength":500},"offlineMessage":{"type":"string","maxLength":500},"agentName":{"type":"string","maxLength":80},"preChatFormEnabled":{"type":"boolean"},"preChatFormFields":{"type":"array","maxItems":10,"items":{"type":"object"}}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/live-chat/widget/avatar:
    put:
      x-seedly-oauth-scope: "live-chat:manage"
      x-seedly-standard-scope: "live-chat:manage"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: setLiveChatAvatar
      tags: [Live Chat]
      summary: "Set the live chat avatar"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Also requires files:read, because the avatar is displayed on the public widget. fileId names an unlinked PNG, JPEG, WebP or GIF file uploaded with purpose avatar. Replacing an avatar keeps the earlier file. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["fileId"],"properties":{"fileId":{"type":"string"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "live-chat:manage"
      x-seedly-standard-scope: "live-chat:manage"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: clearLiveChatAvatar
      tags: [Live Chat]
      summary: "Clear the live chat avatar"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Removes the avatar from the public widget. A stored file that held it stays in Files. Requires Idempotency-Key. Replays recheck current authority and return the original receipt without repeating effects."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '409':
          description: Idempotency-Key reused with different details or stale state.
        '429':
          description: Rate limit exceeded.

  /api/v1/live-chat/sessions:
    get:
      x-seedly-oauth-scope: "conversations:read"
      x-seedly-standard-scope: "conversations:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listLiveChatSessions
      tags: [Conversations]
      summary: "List chat sessions"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Requires conversations:read and contacts:read. Newest first. Visitor session tokens are never returned; they stay bound to the visitor widget. Reply through the conversation message routes."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":8192}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/live-chat/sessions/{id}:
    get:
      x-seedly-oauth-scope: "conversations:read"
      x-seedly-standard-scope: "conversations:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getLiveChatSession
      tags: [Conversations]
      summary: "Read a chat session"
      description: "Location-wide only: Standard v2 or OAuth with exact operation approval. Legacy API keys and own, team or selected record grants are denied. Requires conversations:read and contacts:read. Visitor session tokens are never returned."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input, unsupported query or missing Idempotency-Key.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, restricted grant or legacy key.
        '404':
          description: Record is not available to this credential.
        '429':
          description: Rate limit exceeded.

  /api/v1/tasks/{id}/assignees:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-record-grant-approvals: {"minPolicyVersion":12,"options":["allowTaskMetadata"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: Read the task assignment set
      description: >-
        Requires fresh tasks:read operation approval. Returns only distinct user IDs, no profile data.
        Own/team/selected access requires explicit version12 allowTaskMetadata approval.
        Current task creator or any assignee must satisfy the pinned record and native role boundary.
        All child rows must match the exact task and tenant. The complete response is bounded to100
        assignment rows and64KiB; oversized legacy records fail without a partial response. No pagination.
        Legacy API keys are unsupported; existing task endpoints remain unchanged.
      parameters:
        - {name: id, in: path, required: true, schema: {type: string}}
      responses:
        '200':
          description: Complete assignment set
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: array
                    maxItems: 100
                    items: {type: object, required: [userId], properties: {userId: {type: string}}}
        '400': {description: Invalid input or bounded capacity exceeded}
        '403': {description: Missing current task or operation authority}
    put:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-record-grant-approvals: {"minPolicyVersion":12,"options":["allowTaskMetadata","allowReassign"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: Replace the complete task assignment set
      description: >-
        Requires fresh tasks:write operation approval and Idempotency-Key. Restricted grants additionally
        require version12 allowTaskMetadata plus allowReassign. Empty arrays remove all assignments only
        when the task remains within current ownership after the change. Duplicate IDs are rejected.
        Every desired user must be active and able to reach this location; restricted grants also limit
        candidates to the approved current own/team subject. Linked contact/deal read authority is required.
        Retries prove current stored assignees, live related records and effective OAuth scopes before
        returning the original receipt; they do not reapply old proposed assignments. User and membership
        proof data is capped at512KiB, each user/membership page at64KiB and100 memberships.
        Actual changes preserve task activity, audit and task_updated workflow semantics. No-op and replay
        emit no duplicate effects. Deferred task_updated events retain the exact credential and OAuth token scope ceiling; admission rechecks current task, relationships and pipeline access against pinned task relationships before firing the original bounded event once; later authorized metadata or title edits do not erase earlier events. Standard machines never impersonate their creator. Legacy keys denied.
      parameters:
        - {name: id, in: path, required: true, schema: {type: string}}
        - {name: Idempotency-Key, in: header, required: true, schema: {type: string, minLength: 8, maxLength: 128}}
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              required: [userIds]
              properties:
                userIds: {type: array, uniqueItems: true, maxItems: 100, items: {type: string}}
      responses:
        '200':
          description: Durable update receipt
          content:
            application/json:
              schema:
                type: object
                properties:
                  data: {type: object, required: [id, updated], properties: {id: {type: string}, updated: {const: true}}}
        '400': {description: Invalid input or bounded capacity exceeded}
        '403': {description: Missing current task, relationship or assignment authority}
        '409': {description: Idempotency key reused with another payload}

  /api/v1/tasks/{id}/subtasks:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-record-grant-approvals: {"minPolicyVersion":11,"options":["allowTaskDetails"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "taskDetails0"
      tags: ["Tasks"]
      summary: "Get task subtasks"
      description: "New explicit operation approval. Location-wide approvals remain supported. Own/team/selected grants require explicit allowTaskDetails approval under policy version11; old grants gain no access. Current task ownership includes all assignees, and child tenant/parent relationships are checked. Archive/restore and subtask completion additionally require allowLifecycle; dependency writes require allowRelink and independent blocker view access. Restricted writes recheck linked contact/opportunity access. Duplicate needs location-wide authority or version13 allowTaskDuplicate with allowCreate and allowTaskDetails on an own or team grant; the copy is created as the approved subject, copied assignees also need allowReassign, and selected grants are denied. Legacy keys are unsupported. Every task and child record is independently tenant checked. Read pages default25/max50 with opaque cursor (max8192 characters). Writes require Idempotency-Key and reauthorize on retry. Subtasks use title max500; reorder accepts at most100 distinct child IDs. Dependency mutations additionally require separately approved GET /tasks/:id under tasks:read and reject cycles or graphs above1000 edges. Duplicate requires tasks:read, contacts:read/opportunities:read when copying those relationships, at most100 subtasks (512 KiB total stored subtask data) and50 assignees; assignee location access is rechecked. OAuth comments are authored by the consenting user. A location-wide Standard key writes as itself with no human author, and a filtered Standard key cannot write comments. Update is author-only; delete is author or, for OAuth, native agency owner; leaf comments only and at most 100 mention cleanup rows. Create accepts up to 25 mentionedUserIds with users:read approval; users outside the location are dropped and the receipt lists who was kept. Filtered grants cannot mention. Mention creation is not accepted. Durable large duplication, filtered duplication, machine authorship and notification contracts are not advertised. Dependency pages may be empty after access filtering; continue while meta.hasMore is true."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 50, "default": 25}}, {"name": "cursor", "in": "query", "schema": {"type": "string", "maxLength": 8192}}]
      responses: {"200": {"description": "Collection envelope (data array and meta.limit/hasMore/cursor), or durable write receipt. Mutation receipts contain id; subtask receipts add updated:true, archive/restore archived:boolean, dependencies blockingTaskId and removed:boolean, comments updated:true and actorUserId.", "content": {"application/json": {"schema": {"type": "object", "required": ["data", "meta"], "properties": {"data": {"type": "array", "items": {"type": "object", "required": ["id", "title", "completed", "completedAt", "sortOrder", "updatedAt"], "properties": {"id": {"type": "string"}, "title": {"type": "string"}, "completed": {"type": "boolean"}, "completedAt": {"type": ["number", "null"]}, "sortOrder": {"type": "number"}, "updatedAt": {"type": "number"}}}}, "meta": {"type": "object", "required": ["limit", "hasMore", "cursor"], "properties": {"limit": {"type": "integer"}, "hasMore": {"type": "boolean"}, "cursor": {"type": ["string", "null"]}}}}}}}}, "400": {"description": "Invalid payload, cursor or bounded capacity exceeded."}, "403": {"description": "Missing live authorization or unsupported grant/credential."}, "409": {"description": "Dependency cycle or idempotency conflict."}, "429": {"description": "Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-record-grant-approvals: {"minPolicyVersion":11,"options":["allowTaskDetails"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "taskDetails1"
      tags: ["Tasks"]
      summary: "Post task subtasks"
      description: "New explicit operation approval. Location-wide approvals remain supported. Own/team/selected grants require explicit allowTaskDetails approval under policy version11; old grants gain no access. Current task ownership includes all assignees, and child tenant/parent relationships are checked. Archive/restore and subtask completion additionally require allowLifecycle; dependency writes require allowRelink and independent blocker view access. Restricted writes recheck linked contact/opportunity access. Duplicate needs location-wide authority or version13 allowTaskDuplicate with allowCreate and allowTaskDetails on an own or team grant; the copy is created as the approved subject, copied assignees also need allowReassign, and selected grants are denied. Legacy keys are unsupported. Every task and child record is independently tenant checked. Read pages default25/max50 with opaque cursor (max8192 characters). Writes require Idempotency-Key and reauthorize on retry. Subtasks use title max500; reorder accepts at most100 distinct child IDs. Dependency mutations additionally require separately approved GET /tasks/:id under tasks:read and reject cycles or graphs above1000 edges. Duplicate requires tasks:read, contacts:read/opportunities:read when copying those relationships, at most100 subtasks (512 KiB total stored subtask data) and50 assignees; assignee location access is rechecked. OAuth comments are authored by the consenting user. A location-wide Standard key writes as itself with no human author, and a filtered Standard key cannot write comments. Update is author-only; delete is author or, for OAuth, native agency owner; leaf comments only and at most 100 mention cleanup rows. Create accepts up to 25 mentionedUserIds with users:read approval; users outside the location are dropped and the receipt lists who was kept. Filtered grants cannot mention. Mention creation is not accepted. Durable large duplication, filtered duplication, machine authorship and notification contracts are not advertised. Dependency pages may be empty after access filtering; continue while meta.hasMore is true."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "minLength": 8, "maxLength": 128}}]
      responses: {"200": {"description": "Collection envelope (data array and meta.limit/hasMore/cursor), or durable write receipt. Mutation receipts contain id; subtask receipts add updated:true, archive/restore archived:boolean, dependencies blockingTaskId and removed:boolean, comments updated:true and actorUserId.", "content": {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"type": "object", "required": ["id", "updated"], "properties": {"id": {"type": "string"}, "updated": {"const": true}}}}}}}}, "400": {"description": "Invalid payload, cursor or bounded capacity exceeded."}, "403": {"description": "Missing live authorization or unsupported grant/credential."}, "409": {"description": "Dependency cycle or idempotency conflict."}, "429": {"description": "Rate limit exceeded."}}
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"title": {"type": "string", "minLength": 1, "maxLength": 500}}, "required": ["title"]}}}}

  /api/v1/tasks/{id}/subtasks/{childId}:
    patch:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-record-grant-approvals: {"minPolicyVersion":11,"options":["allowTaskDetails","allowLifecycle"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "taskDetails2"
      tags: ["Tasks"]
      summary: "Patch task subtasks"
      description: "New explicit operation approval. Location-wide approvals remain supported. Own/team/selected grants require explicit allowTaskDetails approval under policy version11; old grants gain no access. Current task ownership includes all assignees, and child tenant/parent relationships are checked. Archive/restore and subtask completion additionally require allowLifecycle; dependency writes require allowRelink and independent blocker view access. Restricted writes recheck linked contact/opportunity access. Duplicate needs location-wide authority or version13 allowTaskDuplicate with allowCreate and allowTaskDetails on an own or team grant; the copy is created as the approved subject, copied assignees also need allowReassign, and selected grants are denied. Legacy keys are unsupported. Every task and child record is independently tenant checked. Read pages default25/max50 with opaque cursor (max8192 characters). Writes require Idempotency-Key and reauthorize on retry. Subtasks use title max500; reorder accepts at most100 distinct child IDs. Dependency mutations additionally require separately approved GET /tasks/:id under tasks:read and reject cycles or graphs above1000 edges. Duplicate requires tasks:read, contacts:read/opportunities:read when copying those relationships, at most100 subtasks (512 KiB total stored subtask data) and50 assignees; assignee location access is rechecked. OAuth comments are authored by the consenting user. A location-wide Standard key writes as itself with no human author, and a filtered Standard key cannot write comments. Update is author-only; delete is author or, for OAuth, native agency owner; leaf comments only and at most 100 mention cleanup rows. Create accepts up to 25 mentionedUserIds with users:read approval; users outside the location are dropped and the receipt lists who was kept. Filtered grants cannot mention. Mention creation is not accepted. Durable large duplication, filtered duplication, machine authorship and notification contracts are not advertised. Dependency pages may be empty after access filtering; continue while meta.hasMore is true."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "childId", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "minLength": 8, "maxLength": 128}}]
      responses: {"200": {"description": "Collection envelope (data array and meta.limit/hasMore/cursor), or durable write receipt. Mutation receipts contain id; subtask receipts add updated:true, archive/restore archived:boolean, dependencies blockingTaskId and removed:boolean, comments updated:true and actorUserId.", "content": {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"type": "object", "required": ["id", "updated"], "properties": {"id": {"type": "string"}, "updated": {"const": true}}}}}}}}, "400": {"description": "Invalid payload, cursor or bounded capacity exceeded."}, "403": {"description": "Missing live authorization or unsupported grant/credential."}, "409": {"description": "Dependency cycle or idempotency conflict."}, "429": {"description": "Rate limit exceeded."}}
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"title": {"type": "string", "minLength": 1, "maxLength": 500}, "completed": {"type": "boolean"}}, "minProperties": 1}}}}
    delete:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-record-grant-approvals: {"minPolicyVersion":11,"options":["allowTaskDetails"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "taskDetails3"
      tags: ["Tasks"]
      summary: "Delete task subtasks"
      description: "New explicit operation approval. Location-wide approvals remain supported. Own/team/selected grants require explicit allowTaskDetails approval under policy version11; old grants gain no access. Current task ownership includes all assignees, and child tenant/parent relationships are checked. Archive/restore and subtask completion additionally require allowLifecycle; dependency writes require allowRelink and independent blocker view access. Restricted writes recheck linked contact/opportunity access. Duplicate needs location-wide authority or version13 allowTaskDuplicate with allowCreate and allowTaskDetails on an own or team grant; the copy is created as the approved subject, copied assignees also need allowReassign, and selected grants are denied. Legacy keys are unsupported. Every task and child record is independently tenant checked. Read pages default25/max50 with opaque cursor (max8192 characters). Writes require Idempotency-Key and reauthorize on retry. Subtasks use title max500; reorder accepts at most100 distinct child IDs. Dependency mutations additionally require separately approved GET /tasks/:id under tasks:read and reject cycles or graphs above1000 edges. Duplicate requires tasks:read, contacts:read/opportunities:read when copying those relationships, at most100 subtasks (512 KiB total stored subtask data) and50 assignees; assignee location access is rechecked. OAuth comments are authored by the consenting user. A location-wide Standard key writes as itself with no human author, and a filtered Standard key cannot write comments. Update is author-only; delete is author or, for OAuth, native agency owner; leaf comments only and at most 100 mention cleanup rows. Create accepts up to 25 mentionedUserIds with users:read approval; users outside the location are dropped and the receipt lists who was kept. Filtered grants cannot mention. Mention creation is not accepted. Durable large duplication, filtered duplication, machine authorship and notification contracts are not advertised. Dependency pages may be empty after access filtering; continue while meta.hasMore is true."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "childId", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "minLength": 8, "maxLength": 128}}]
      responses: {"200": {"description": "Collection envelope (data array and meta.limit/hasMore/cursor), or durable write receipt. Mutation receipts contain id; subtask receipts add updated:true, archive/restore archived:boolean, dependencies blockingTaskId and removed:boolean, comments updated:true and actorUserId.", "content": {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"type": "object", "required": ["id", "updated"], "properties": {"id": {"type": "string"}, "updated": {"const": true}}}}}}}}, "400": {"description": "Invalid payload, cursor or bounded capacity exceeded."}, "403": {"description": "Missing live authorization or unsupported grant/credential."}, "409": {"description": "Dependency cycle or idempotency conflict."}, "429": {"description": "Rate limit exceeded."}}

  /api/v1/tasks/{id}/subtasks/reorder:
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-record-grant-approvals: {"minPolicyVersion":11,"options":["allowTaskDetails"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "taskDetails4"
      tags: ["Tasks"]
      summary: "Post task subtasks"
      description: "New explicit operation approval. Location-wide approvals remain supported. Own/team/selected grants require explicit allowTaskDetails approval under policy version11; old grants gain no access. Current task ownership includes all assignees, and child tenant/parent relationships are checked. Archive/restore and subtask completion additionally require allowLifecycle; dependency writes require allowRelink and independent blocker view access. Restricted writes recheck linked contact/opportunity access. Duplicate needs location-wide authority or version13 allowTaskDuplicate with allowCreate and allowTaskDetails on an own or team grant; the copy is created as the approved subject, copied assignees also need allowReassign, and selected grants are denied. Legacy keys are unsupported. Every task and child record is independently tenant checked. Read pages default25/max50 with opaque cursor (max8192 characters). Writes require Idempotency-Key and reauthorize on retry. Subtasks use title max500; reorder accepts at most100 distinct child IDs. Dependency mutations additionally require separately approved GET /tasks/:id under tasks:read and reject cycles or graphs above1000 edges. Duplicate requires tasks:read, contacts:read/opportunities:read when copying those relationships, at most100 subtasks (512 KiB total stored subtask data) and50 assignees; assignee location access is rechecked. OAuth comments are authored by the consenting user. A location-wide Standard key writes as itself with no human author, and a filtered Standard key cannot write comments. Update is author-only; delete is author or, for OAuth, native agency owner; leaf comments only and at most 100 mention cleanup rows. Create accepts up to 25 mentionedUserIds with users:read approval; users outside the location are dropped and the receipt lists who was kept. Filtered grants cannot mention. Mention creation is not accepted. Durable large duplication, filtered duplication, machine authorship and notification contracts are not advertised. Dependency pages may be empty after access filtering; continue while meta.hasMore is true."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "minLength": 8, "maxLength": 128}}]
      responses: {"200": {"description": "Collection envelope (data array and meta.limit/hasMore/cursor), or durable write receipt. Mutation receipts contain id; subtask receipts add updated:true, archive/restore archived:boolean, dependencies blockingTaskId and removed:boolean, comments updated:true and actorUserId.", "content": {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"type": "object", "required": ["id", "updated"], "properties": {"id": {"type": "string"}, "updated": {"const": true}}}}}}}}, "400": {"description": "Invalid payload, cursor or bounded capacity exceeded."}, "403": {"description": "Missing live authorization or unsupported grant/credential."}, "409": {"description": "Dependency cycle or idempotency conflict."}, "429": {"description": "Rate limit exceeded."}}
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"ids": {"type": "array", "minItems": 1, "maxItems": 100, "uniqueItems": true, "items": {"type": "string"}}}, "required": ["ids"]}}}}

  /api/v1/tasks/{id}/dependencies:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-record-grant-approvals: {"minPolicyVersion":11,"options":["allowTaskDetails"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "taskDetails5"
      tags: ["Tasks"]
      summary: "Get task dependencies"
      description: "New explicit operation approval. Location-wide approvals remain supported. Own/team/selected grants require explicit allowTaskDetails approval under policy version11; old grants gain no access. Current task ownership includes all assignees, and child tenant/parent relationships are checked. Archive/restore and subtask completion additionally require allowLifecycle; dependency writes require allowRelink and independent blocker view access. Restricted writes recheck linked contact/opportunity access. Duplicate needs location-wide authority or version13 allowTaskDuplicate with allowCreate and allowTaskDetails on an own or team grant; the copy is created as the approved subject, copied assignees also need allowReassign, and selected grants are denied. Legacy keys are unsupported. Every task and child record is independently tenant checked. Dependency pages cap the effective limit at2 even if a request asks for up to50. Each edge validates its opposite full task and project; meta.limit reports the effective limit and the cursor preserves every edge. Opaque cursors have max8192 characters. Writes require Idempotency-Key and reauthorize on retry. Subtasks use title max500; reorder accepts at most100 distinct child IDs. Dependency mutations additionally require separately approved GET /tasks/:id under tasks:read and reject cycles or graphs above1000 edges. Duplicate requires tasks:read, contacts:read/opportunities:read when copying those relationships, at most100 subtasks (512 KiB total stored subtask data) and50 assignees; assignee location access is rechecked. OAuth comments are authored by the consenting user. A location-wide Standard key writes as itself with no human author, and a filtered Standard key cannot write comments. Update is author-only; delete is author or, for OAuth, native agency owner; leaf comments only and at most 100 mention cleanup rows. Create accepts up to 25 mentionedUserIds with users:read approval; users outside the location are dropped and the receipt lists who was kept. Filtered grants cannot mention. Mention creation is not accepted. Durable large duplication, filtered duplication, machine authorship and notification contracts are not advertised. Dependency pages may be empty after access filtering; continue while meta.hasMore is true."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 50, "default": 25}}, {"name": "cursor", "in": "query", "schema": {"type": "string", "maxLength": 8192}}]
      responses: {"200": {"description": "Collection envelope (data array and meta.limit/hasMore/cursor), or durable write receipt. Mutation receipts contain id; subtask receipts add updated:true, archive/restore archived:boolean, dependencies blockingTaskId and removed:boolean, comments updated:true and actorUserId.", "content": {"application/json": {"schema": {"type": "object", "required": ["data", "meta"], "properties": {"data": {"type": "array", "items": {"type": "object", "required": ["id", "blockingTaskId", "blockedTaskId"], "properties": {"id": {"type": "string"}, "blockingTaskId": {"type": "string"}, "blockedTaskId": {"type": "string"}}}}, "meta": {"type": "object", "required": ["limit", "hasMore", "cursor"], "properties": {"limit": {"type": "integer"}, "hasMore": {"type": "boolean"}, "cursor": {"type": ["string", "null"]}}}}}}}}, "400": {"description": "Invalid payload, cursor or bounded capacity exceeded."}, "403": {"description": "Missing live authorization or unsupported grant/credential."}, "409": {"description": "Dependency cycle or idempotency conflict."}, "429": {"description": "Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-record-grant-approvals: {"minPolicyVersion":11,"options":["allowTaskDetails","allowRelink"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "taskDetails6"
      tags: ["Tasks"]
      summary: "Post task dependencies"
      description: "New explicit operation approval. Location-wide approvals remain supported. Own/team/selected grants require explicit allowTaskDetails approval under policy version11; old grants gain no access. Current task ownership includes all assignees, and child tenant/parent relationships are checked. Archive/restore and subtask completion additionally require allowLifecycle; dependency writes require allowRelink and independent blocker view access. Restricted writes recheck linked contact/opportunity access. Duplicate needs location-wide authority or version13 allowTaskDuplicate with allowCreate and allowTaskDetails on an own or team grant; the copy is created as the approved subject, copied assignees also need allowReassign, and selected grants are denied. Legacy keys are unsupported. Every task and child record is independently tenant checked. Read pages default25/max50 with opaque cursor (max8192 characters). Writes require Idempotency-Key and reauthorize on retry. Subtasks use title max500; reorder accepts at most100 distinct child IDs. Dependency mutations additionally require separately approved GET /tasks/:id under tasks:read and reject cycles or graphs above1000 edges. Duplicate requires tasks:read, contacts:read/opportunities:read when copying those relationships, at most100 subtasks (512 KiB total stored subtask data) and50 assignees; assignee location access is rechecked. OAuth comments are authored by the consenting user. A location-wide Standard key writes as itself with no human author, and a filtered Standard key cannot write comments. Update is author-only; delete is author or, for OAuth, native agency owner; leaf comments only and at most 100 mention cleanup rows. Create accepts up to 25 mentionedUserIds with users:read approval; users outside the location are dropped and the receipt lists who was kept. Filtered grants cannot mention. Mention creation is not accepted. Durable large duplication, filtered duplication, machine authorship and notification contracts are not advertised. Dependency pages may be empty after access filtering; continue while meta.hasMore is true."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "minLength": 8, "maxLength": 128}}]
      responses: {"200": {"description": "Collection envelope (data array and meta.limit/hasMore/cursor), or durable write receipt. Mutation receipts contain id; subtask receipts add updated:true, archive/restore archived:boolean, dependencies blockingTaskId and removed:boolean, comments updated:true and actorUserId.", "content": {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"type": "object", "required": ["id", "blockingTaskId", "removed"], "properties": {"id": {"type": "string"}, "blockingTaskId": {"type": "string"}, "removed": {"type": "boolean"}}}}}}}}, "400": {"description": "Invalid payload, cursor or bounded capacity exceeded."}, "403": {"description": "Missing live authorization or unsupported grant/credential."}, "409": {"description": "Dependency cycle or idempotency conflict."}, "429": {"description": "Rate limit exceeded."}}
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"blockingTaskId": {"type": "string"}}, "required": ["blockingTaskId"]}}}}

  /api/v1/tasks/{id}/dependencies/{blockingTaskId}:
    delete:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-record-grant-approvals: {"minPolicyVersion":11,"options":["allowTaskDetails","allowRelink"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "taskDetails7"
      tags: ["Tasks"]
      summary: "Delete task dependencies"
      description: "New explicit operation approval. Location-wide approvals remain supported. Own/team/selected grants require explicit allowTaskDetails approval under policy version11; old grants gain no access. Current task ownership includes all assignees, and child tenant/parent relationships are checked. Archive/restore and subtask completion additionally require allowLifecycle; dependency writes require allowRelink and independent blocker view access. Restricted writes recheck linked contact/opportunity access. Duplicate needs location-wide authority or version13 allowTaskDuplicate with allowCreate and allowTaskDetails on an own or team grant; the copy is created as the approved subject, copied assignees also need allowReassign, and selected grants are denied. Legacy keys are unsupported. Every task and child record is independently tenant checked. Read pages default25/max50 with opaque cursor (max8192 characters). Writes require Idempotency-Key and reauthorize on retry. Subtasks use title max500; reorder accepts at most100 distinct child IDs. Dependency mutations additionally require separately approved GET /tasks/:id under tasks:read and reject cycles or graphs above1000 edges. Duplicate requires tasks:read, contacts:read/opportunities:read when copying those relationships, at most100 subtasks (512 KiB total stored subtask data) and50 assignees; assignee location access is rechecked. OAuth comments are authored by the consenting user. A location-wide Standard key writes as itself with no human author, and a filtered Standard key cannot write comments. Update is author-only; delete is author or, for OAuth, native agency owner; leaf comments only and at most 100 mention cleanup rows. Create accepts up to 25 mentionedUserIds with users:read approval; users outside the location are dropped and the receipt lists who was kept. Filtered grants cannot mention. Mention creation is not accepted. Durable large duplication, filtered duplication, machine authorship and notification contracts are not advertised. Dependency pages may be empty after access filtering; continue while meta.hasMore is true."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "blockingTaskId", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "minLength": 8, "maxLength": 128}}]
      responses: {"200": {"description": "Collection envelope (data array and meta.limit/hasMore/cursor), or durable write receipt. Mutation receipts contain id; subtask receipts add updated:true, archive/restore archived:boolean, dependencies blockingTaskId and removed:boolean, comments updated:true and actorUserId.", "content": {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"type": "object", "required": ["id", "blockingTaskId", "removed"], "properties": {"id": {"type": "string"}, "blockingTaskId": {"type": "string"}, "removed": {"type": "boolean"}}}}}}}}, "400": {"description": "Invalid payload, cursor or bounded capacity exceeded."}, "403": {"description": "Missing live authorization or unsupported grant/credential."}, "409": {"description": "Dependency cycle or idempotency conflict."}, "429": {"description": "Rate limit exceeded."}}

  /api/v1/tasks/{id}/archive:
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-record-grant-approvals: {"minPolicyVersion":11,"options":["allowTaskDetails","allowLifecycle"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "taskDetails8"
      tags: ["Tasks"]
      summary: "Post task archive"
      description: "New explicit operation approval. Location-wide approvals remain supported. Own/team/selected grants require explicit allowTaskDetails approval under policy version11; old grants gain no access. Current task ownership includes all assignees, and child tenant/parent relationships are checked. Archive/restore and subtask completion additionally require allowLifecycle; dependency writes require allowRelink and independent blocker view access. Restricted writes recheck linked contact/opportunity access. Duplicate needs location-wide authority or version13 allowTaskDuplicate with allowCreate and allowTaskDetails on an own or team grant; the copy is created as the approved subject, copied assignees also need allowReassign, and selected grants are denied. Legacy keys are unsupported. Every task and child record is independently tenant checked. Read pages default25/max50 with opaque cursor (max8192 characters). Writes require Idempotency-Key and reauthorize on retry. Subtasks use title max500; reorder accepts at most100 distinct child IDs. Dependency mutations additionally require separately approved GET /tasks/:id under tasks:read and reject cycles or graphs above1000 edges. Duplicate requires tasks:read, contacts:read/opportunities:read when copying those relationships, at most100 subtasks (512 KiB total stored subtask data) and50 assignees; assignee location access is rechecked. OAuth comments are authored by the consenting user. A location-wide Standard key writes as itself with no human author, and a filtered Standard key cannot write comments. Update is author-only; delete is author or, for OAuth, native agency owner; leaf comments only and at most 100 mention cleanup rows. Create accepts up to 25 mentionedUserIds with users:read approval; users outside the location are dropped and the receipt lists who was kept. Filtered grants cannot mention. Mention creation is not accepted. Durable large duplication, filtered duplication, machine authorship and notification contracts are not advertised. Dependency pages may be empty after access filtering; continue while meta.hasMore is true."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "minLength": 8, "maxLength": 128}}]
      responses: {"200": {"description": "Collection envelope (data array and meta.limit/hasMore/cursor), or durable write receipt. Mutation receipts contain id; subtask receipts add updated:true, archive/restore archived:boolean, dependencies blockingTaskId and removed:boolean, comments updated:true and actorUserId.", "content": {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"type": "object", "required": ["id", "archived"], "properties": {"id": {"type": "string"}, "archived": {"type": "boolean"}}}}}}}}, "400": {"description": "Invalid payload, cursor or bounded capacity exceeded."}, "403": {"description": "Missing live authorization or unsupported grant/credential."}, "409": {"description": "Dependency cycle or idempotency conflict."}, "429": {"description": "Rate limit exceeded."}}
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {}}}}}

  /api/v1/tasks/{id}/restore:
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-record-grant-approvals: {"minPolicyVersion":11,"options":["allowTaskDetails","allowLifecycle"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "taskDetails9"
      tags: ["Tasks"]
      summary: "Post task restore"
      description: "New explicit operation approval. Location-wide approvals remain supported. Own/team/selected grants require explicit allowTaskDetails approval under policy version11; old grants gain no access. Current task ownership includes all assignees, and child tenant/parent relationships are checked. Archive/restore and subtask completion additionally require allowLifecycle; dependency writes require allowRelink and independent blocker view access. Restricted writes recheck linked contact/opportunity access. Duplicate needs location-wide authority or version13 allowTaskDuplicate with allowCreate and allowTaskDetails on an own or team grant; the copy is created as the approved subject, copied assignees also need allowReassign, and selected grants are denied. Legacy keys are unsupported. Every task and child record is independently tenant checked. Read pages default25/max50 with opaque cursor (max8192 characters). Writes require Idempotency-Key and reauthorize on retry. Subtasks use title max500; reorder accepts at most100 distinct child IDs. Dependency mutations additionally require separately approved GET /tasks/:id under tasks:read and reject cycles or graphs above1000 edges. Duplicate requires tasks:read, contacts:read/opportunities:read when copying those relationships, at most100 subtasks (512 KiB total stored subtask data) and50 assignees; assignee location access is rechecked. OAuth comments are authored by the consenting user. A location-wide Standard key writes as itself with no human author, and a filtered Standard key cannot write comments. Update is author-only; delete is author or, for OAuth, native agency owner; leaf comments only and at most 100 mention cleanup rows. Create accepts up to 25 mentionedUserIds with users:read approval; users outside the location are dropped and the receipt lists who was kept. Filtered grants cannot mention. Mention creation is not accepted. Durable large duplication, filtered duplication, machine authorship and notification contracts are not advertised. Dependency pages may be empty after access filtering; continue while meta.hasMore is true."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "minLength": 8, "maxLength": 128}}]
      responses: {"200": {"description": "Collection envelope (data array and meta.limit/hasMore/cursor), or durable write receipt. Mutation receipts contain id; subtask receipts add updated:true, archive/restore archived:boolean, dependencies blockingTaskId and removed:boolean, comments updated:true and actorUserId.", "content": {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"type": "object", "required": ["id", "archived"], "properties": {"id": {"type": "string"}, "archived": {"type": "boolean"}}}}}}}}, "400": {"description": "Invalid payload, cursor or bounded capacity exceeded."}, "403": {"description": "Missing live authorization or unsupported grant/credential."}, "409": {"description": "Dependency cycle or idempotency conflict."}, "429": {"description": "Rate limit exceeded."}}
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {}}}}}

  /api/v1/tasks/{id}/duplicate:
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-record-grant-approvals: {"minPolicyVersion":13,"options":["allowTaskDuplicate"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "taskDetails10"
      tags: ["Tasks"]
      summary: "Post task duplicate"
      description: "New explicit operation approval. Location-wide approvals remain supported. Own/team/selected grants require explicit allowTaskDetails approval under policy version11; old grants gain no access. Current task ownership includes all assignees, and child tenant/parent relationships are checked. Archive/restore and subtask completion additionally require allowLifecycle; dependency writes require allowRelink and independent blocker view access. Restricted writes recheck linked contact/opportunity access. Duplicate needs location-wide authority or version13 allowTaskDuplicate with allowCreate and allowTaskDetails on an own or team grant; the copy is created as the approved subject, copied assignees also need allowReassign, and selected grants are denied. Legacy keys are unsupported. Every task and child record is independently tenant checked. Read pages default25/max50 with opaque cursor (max8192 characters). Writes require Idempotency-Key and reauthorize on retry. Subtasks use title max500; reorder accepts at most100 distinct child IDs. Dependency mutations additionally require separately approved GET /tasks/:id under tasks:read and reject cycles or graphs above1000 edges. Duplicate requires tasks:read, contacts:read/opportunities:read when copying those relationships, at most100 subtasks (512 KiB total stored subtask data) and50 assignees; assignee location access is rechecked. OAuth comments are authored by the consenting user. A location-wide Standard key writes as itself with no human author, and a filtered Standard key cannot write comments. Update is author-only; delete is author or, for OAuth, native agency owner; leaf comments only and at most 100 mention cleanup rows. Create accepts up to 25 mentionedUserIds with users:read approval; users outside the location are dropped and the receipt lists who was kept. Filtered grants cannot mention. Mention creation is not accepted. Durable large duplication, filtered duplication, machine authorship and notification contracts are not advertised. Dependency pages may be empty after access filtering; continue while meta.hasMore is true."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "minLength": 8, "maxLength": 128}}]
      responses: {"200": {"description": "Collection envelope (data array and meta.limit/hasMore/cursor), or durable write receipt. Mutation receipts contain id; subtask receipts add updated:true, archive/restore archived:boolean, dependencies blockingTaskId and removed:boolean, comments updated:true and actorUserId.", "content": {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"type": "object", "required": ["id"], "properties": {"id": {"type": "string"}}}}}}}}, "400": {"description": "Invalid payload, cursor or bounded capacity exceeded."}, "403": {"description": "Missing live authorization or unsupported grant/credential."}, "409": {"description": "Dependency cycle or idempotency conflict."}, "429": {"description": "Rate limit exceeded."}}
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"includeSubtasks": {"type": "boolean"}, "includeAssignees": {"type": "boolean"}, "includeTags": {"type": "boolean"}, "includeDescription": {"type": "boolean"}}}}}}

  /api/v1/tasks/{id}/comments:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-record-grant-approvals: {"minPolicyVersion":11,"options":["allowTaskDetails"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "taskDetails11"
      tags: ["Tasks"]
      summary: "Get task comments"
      description: "New explicit operation approval. Location-wide approvals remain supported. Own/team/selected grants require explicit allowTaskDetails approval under policy version11; old grants gain no access. Current task ownership includes all assignees, and child tenant/parent relationships are checked. Archive/restore and subtask completion additionally require allowLifecycle; dependency writes require allowRelink and independent blocker view access. Restricted writes recheck linked contact/opportunity access. Duplicate needs location-wide authority or version13 allowTaskDuplicate with allowCreate and allowTaskDetails on an own or team grant; the copy is created as the approved subject, copied assignees also need allowReassign, and selected grants are denied. Legacy keys are unsupported. Every task and child record is independently tenant checked. Read pages default25/max50 with opaque cursor (max8192 characters). Writes require Idempotency-Key and reauthorize on retry. Subtasks use title max500; reorder accepts at most100 distinct child IDs. Dependency mutations additionally require separately approved GET /tasks/:id under tasks:read and reject cycles or graphs above1000 edges. Duplicate requires tasks:read, contacts:read/opportunities:read when copying those relationships, at most100 subtasks (512 KiB total stored subtask data) and50 assignees; assignee location access is rechecked. OAuth comments are authored by the consenting user. A location-wide Standard key writes as itself with no human author, and a filtered Standard key cannot write comments. Update is author-only; delete is author or, for OAuth, native agency owner; leaf comments only and at most 100 mention cleanup rows. Create accepts up to 25 mentionedUserIds with users:read approval; users outside the location are dropped and the receipt lists who was kept. Filtered grants cannot mention. Mention creation is not accepted. Durable large duplication, filtered duplication, machine authorship and notification contracts are not advertised. Dependency pages may be empty after access filtering; continue while meta.hasMore is true."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 50, "default": 25}}, {"name": "cursor", "in": "query", "schema": {"type": "string", "maxLength": 8192}}]
      responses: {"200": {"description": "Collection envelope (data array and meta.limit/hasMore/cursor), or durable write receipt. Mutation receipts contain id; subtask receipts add updated:true, archive/restore archived:boolean, dependencies blockingTaskId and removed:boolean, comments updated:true and actorUserId.", "content": {"application/json": {"schema": {"type": "object", "required": ["data", "meta"], "properties": {"data": {"type": "array", "items": {"type": "object", "required": ["id", "userId", "content", "parentCommentId", "createdAt", "updatedAt"], "properties": {"id": {"type": "string"}, "userId": {"type": "string"}, "content": {"type": "string"}, "parentCommentId": {"type": ["string", "null"]}, "createdAt": {"type": "number"}, "updatedAt": {"type": "number"}}}}, "meta": {"type": "object", "required": ["limit", "hasMore", "cursor"], "properties": {"limit": {"type": "integer"}, "hasMore": {"type": "boolean"}, "cursor": {"type": ["string", "null"]}}}}}}}}, "400": {"description": "Invalid payload, cursor or bounded capacity exceeded."}, "403": {"description": "Missing live authorization or unsupported grant/credential."}, "409": {"description": "Dependency cycle or idempotency conflict."}, "429": {"description": "Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-record-grant-approvals: {"minPolicyVersion":11,"options":["allowTaskDetails"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "taskDetails12"
      tags: ["Tasks"]
      summary: "Post task comments"
      description: "New explicit operation approval. Location-wide approvals remain supported. Own/team/selected grants require explicit allowTaskDetails approval under policy version11; old grants gain no access. Current task ownership includes all assignees, and child tenant/parent relationships are checked. Archive/restore and subtask completion additionally require allowLifecycle; dependency writes require allowRelink and independent blocker view access. Restricted writes recheck linked contact/opportunity access. Duplicate needs location-wide authority or version13 allowTaskDuplicate with allowCreate and allowTaskDetails on an own or team grant; the copy is created as the approved subject, copied assignees also need allowReassign, and selected grants are denied. Legacy keys are unsupported. Every task and child record is independently tenant checked. Read pages default25/max50 with opaque cursor (max8192 characters). Writes require Idempotency-Key and reauthorize on retry. Subtasks use title max500; reorder accepts at most100 distinct child IDs. Dependency mutations additionally require separately approved GET /tasks/:id under tasks:read and reject cycles or graphs above1000 edges. Duplicate requires tasks:read, contacts:read/opportunities:read when copying those relationships, at most100 subtasks (512 KiB total stored subtask data) and50 assignees; assignee location access is rechecked. OAuth comments are authored by the consenting user. A location-wide Standard key writes as itself with no human author, and a filtered Standard key cannot write comments. Update is author-only; delete is author or, for OAuth, native agency owner; leaf comments only and at most 100 mention cleanup rows. Create accepts up to 25 mentionedUserIds with users:read approval; users outside the location are dropped and the receipt lists who was kept. Filtered grants cannot mention. Mention creation is not accepted. Durable large duplication, filtered duplication, machine authorship and notification contracts are not advertised. Dependency pages may be empty after access filtering; continue while meta.hasMore is true."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "minLength": 8, "maxLength": 128}}]
      responses: {"200": {"description": "Collection envelope (data array and meta.limit/hasMore/cursor), or durable write receipt. Mutation receipts contain id; subtask receipts add updated:true, archive/restore archived:boolean, dependencies blockingTaskId and removed:boolean, comments updated:true and actorUserId.", "content": {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"type": "object", "required": ["id", "updated", "actorUserId"], "properties": {"id": {"type": "string"}, "updated": {"const": true}, "actorUserId": {"type": "string"}}}}}}}}, "400": {"description": "Invalid payload, cursor or bounded capacity exceeded."}, "403": {"description": "Missing live authorization or unsupported grant/credential."}, "409": {"description": "Dependency cycle or idempotency conflict."}, "429": {"description": "Rate limit exceeded."}}
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"content": {"type": "string", "minLength": 1, "maxLength": 10000}, "parentCommentId": {"type": "string"}}, "required": ["content"]}}}}

  /api/v1/tasks/{id}/comments/{commentId}:
    patch:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-record-grant-approvals: {"minPolicyVersion":11,"options":["allowTaskDetails"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "taskDetails13"
      tags: ["Tasks"]
      summary: "Patch task comments"
      description: "New explicit operation approval. Location-wide approvals remain supported. Own/team/selected grants require explicit allowTaskDetails approval under policy version11; old grants gain no access. Current task ownership includes all assignees, and child tenant/parent relationships are checked. Archive/restore and subtask completion additionally require allowLifecycle; dependency writes require allowRelink and independent blocker view access. Restricted writes recheck linked contact/opportunity access. Duplicate needs location-wide authority or version13 allowTaskDuplicate with allowCreate and allowTaskDetails on an own or team grant; the copy is created as the approved subject, copied assignees also need allowReassign, and selected grants are denied. Legacy keys are unsupported. Every task and child record is independently tenant checked. Read pages default25/max50 with opaque cursor (max8192 characters). Writes require Idempotency-Key and reauthorize on retry. Subtasks use title max500; reorder accepts at most100 distinct child IDs. Dependency mutations additionally require separately approved GET /tasks/:id under tasks:read and reject cycles or graphs above1000 edges. Duplicate requires tasks:read, contacts:read/opportunities:read when copying those relationships, at most100 subtasks (512 KiB total stored subtask data) and50 assignees; assignee location access is rechecked. OAuth comments are authored by the consenting user. A location-wide Standard key writes as itself with no human author, and a filtered Standard key cannot write comments. Update is author-only; delete is author or, for OAuth, native agency owner; leaf comments only and at most 100 mention cleanup rows. Create accepts up to 25 mentionedUserIds with users:read approval; users outside the location are dropped and the receipt lists who was kept. Filtered grants cannot mention. Mention creation is not accepted. Durable large duplication, filtered duplication, machine authorship and notification contracts are not advertised. Dependency pages may be empty after access filtering; continue while meta.hasMore is true."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "commentId", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "minLength": 8, "maxLength": 128}}]
      responses: {"200": {"description": "Collection envelope (data array and meta.limit/hasMore/cursor), or durable write receipt. Mutation receipts contain id; subtask receipts add updated:true, archive/restore archived:boolean, dependencies blockingTaskId and removed:boolean, comments updated:true and actorUserId.", "content": {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"type": "object", "required": ["id", "updated", "actorUserId"], "properties": {"id": {"type": "string"}, "updated": {"const": true}, "actorUserId": {"type": "string"}}}}}}}}, "400": {"description": "Invalid payload, cursor or bounded capacity exceeded."}, "403": {"description": "Missing live authorization or unsupported grant/credential."}, "409": {"description": "Dependency cycle or idempotency conflict."}, "429": {"description": "Rate limit exceeded."}}
      requestBody: {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"content": {"type": "string", "minLength": 1, "maxLength": 10000}, "parentCommentId": {"type": "string"}, "mentionedUserIds": {"type": "array", "uniqueItems": true, "maxItems": 25, "items": {"type": "string"}}}, "required": ["content"]}}}}
    delete:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-record-grant-approvals: {"minPolicyVersion":11,"options":["allowTaskDetails"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: "taskDetails14"
      tags: ["Tasks"]
      summary: "Delete task comments"
      description: "New explicit operation approval. Location-wide approvals remain supported. Own/team/selected grants require explicit allowTaskDetails approval under policy version11; old grants gain no access. Current task ownership includes all assignees, and child tenant/parent relationships are checked. Archive/restore and subtask completion additionally require allowLifecycle; dependency writes require allowRelink and independent blocker view access. Restricted writes recheck linked contact/opportunity access. Duplicate needs location-wide authority or version13 allowTaskDuplicate with allowCreate and allowTaskDetails on an own or team grant; the copy is created as the approved subject, copied assignees also need allowReassign, and selected grants are denied. Legacy keys are unsupported. Every task and child record is independently tenant checked. Read pages default25/max50 with opaque cursor (max8192 characters). Writes require Idempotency-Key and reauthorize on retry. Subtasks use title max500; reorder accepts at most100 distinct child IDs. Dependency mutations additionally require separately approved GET /tasks/:id under tasks:read and reject cycles or graphs above1000 edges. Duplicate requires tasks:read, contacts:read/opportunities:read when copying those relationships, at most100 subtasks (512 KiB total stored subtask data) and50 assignees; assignee location access is rechecked. OAuth comments are authored by the consenting user. A location-wide Standard key writes as itself with no human author, and a filtered Standard key cannot write comments. Update is author-only; delete is author or, for OAuth, native agency owner; leaf comments only and at most 100 mention cleanup rows. Create accepts up to 25 mentionedUserIds with users:read approval; users outside the location are dropped and the receipt lists who was kept. Filtered grants cannot mention. Mention creation is not accepted. Durable large duplication, filtered duplication, machine authorship and notification contracts are not advertised. Dependency pages may be empty after access filtering; continue while meta.hasMore is true."
      parameters: [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "commentId", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "minLength": 8, "maxLength": 128}}]
      responses: {"200": {"description": "Collection envelope (data array and meta.limit/hasMore/cursor), or durable write receipt. Mutation receipts contain id; subtask receipts add updated:true, archive/restore archived:boolean, dependencies blockingTaskId and removed:boolean, comments updated:true and actorUserId.", "content": {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"type": "object", "required": ["id", "updated", "actorUserId"], "properties": {"id": {"type": "string"}, "updated": {"const": true}, "actorUserId": {"type": "string"}}}}}}}}, "400": {"description": "Invalid payload, cursor or bounded capacity exceeded."}, "403": {"description": "Missing live authorization or unsupported grant/credential."}, "409": {"description": "Dependency cycle or idempotency conflict."}, "429": {"description": "Rate limit exceeded."}}


  /api/v1/snippets:
    get:
      x-seedly-oauth-scope: "snippets:read"
      x-seedly-standard-scope: "snippets:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listSnippets
      tags: [Content Assets]
      summary: "listSnippets"
      description: "Explicit location-wide Standard v2 operation approval or OAuth grant required. Legacy keys and own/team/selected-record grants cannot use these operations. Native location permissions apply; OAuth also revalidates the current user. No sending, document signing, workflow execution, or provider calls. Snippet content is stored without sending it. Prebuilt/system/author fields are read-only. Bulk categories require bulk or both scope. Duplicate requires snippets:read in addition to snippets:write and does not copy prebuilt designation. PATCH folderId null moves a snippet to the root. Pages scan at most 50 rows, default 25. Eligibility filters may produce empty pages; follow meta.cursor while hasMore is true. Cursors are bound to the principal, location, collection and filters. "
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}},{"name":"search","in":"query","schema":{"type":"string"}},{"name":"channel","in":"query","schema":{"type":"string"}},{"name":"scope","in":"query","schema":{"type":"string"}},{"name":"folderId","in":"query","schema":{"type":"string"}},{"name":"module","in":"query","schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized data or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid input or unsupported content shape.
        '401':
          description: Missing or invalid credential.
        '403':
          description: Missing scope, stale approval, revoked authority or unsupported record grant.
        '404':
          description: Target unavailable in this location.
        '409':
          description: Conflicting idempotency request or folder deletion in progress.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "snippets:write"
      x-seedly-standard-scope: "snippets:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createSnippet
      tags: [Content Assets]
      summary: "createSnippet"
      description: "Explicit location-wide Standard v2 operation approval or OAuth grant required. Legacy keys and own/team/selected-record grants cannot use these operations. Native location permissions apply; OAuth also revalidates the current user. No sending, document signing, workflow execution, or provider calls. Stable Idempotency-Key required. Unknown fields rejected. Replays recheck current authorization and target relationships, return the original receipt, and do not reapply changes. Snippet content is stored without sending it. Prebuilt/system/author fields are read-only. Bulk categories require bulk or both scope. Duplicate requires snippets:read in addition to snippets:write and does not copy prebuilt designation. PATCH folderId null moves a snippet to the root. "
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentAssetSnippetCreate"}}}}
      responses:
        '200':
          description: Authorized data or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input or unsupported content shape.
        '401':
          description: Missing or invalid credential.
        '403':
          description: Missing scope, stale approval, revoked authority or unsupported record grant.
        '404':
          description: Target unavailable in this location.
        '409':
          description: Conflicting idempotency request or folder deletion in progress.
        '429':
          description: Rate limit exceeded.
  /api/v1/snippets/{id}:
    get:
      x-seedly-oauth-scope: "snippets:read"
      x-seedly-standard-scope: "snippets:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getSnippet
      tags: [Content Assets]
      summary: "getSnippet"
      description: "Explicit location-wide Standard v2 operation approval or OAuth grant required. Legacy keys and own/team/selected-record grants cannot use these operations. Native location permissions apply; OAuth also revalidates the current user. No sending, document signing, workflow execution, or provider calls. Snippet content is stored without sending it. Prebuilt/system/author fields are read-only. Bulk categories require bulk or both scope. Duplicate requires snippets:read in addition to snippets:write and does not copy prebuilt designation. PATCH folderId null moves a snippet to the root. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized data or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input or unsupported content shape.
        '401':
          description: Missing or invalid credential.
        '403':
          description: Missing scope, stale approval, revoked authority or unsupported record grant.
        '404':
          description: Target unavailable in this location.
        '409':
          description: Conflicting idempotency request or folder deletion in progress.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "snippets:write"
      x-seedly-standard-scope: "snippets:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateSnippet
      tags: [Content Assets]
      summary: "updateSnippet"
      description: "A snippet bound to review requests also needs review-requests:send. Explicit location-wide Standard v2 operation approval or OAuth grant required. Legacy keys and own/team/selected-record grants cannot use these operations. Native location permissions apply; OAuth also revalidates the current user. No sending, document signing, workflow execution, or provider calls. Stable Idempotency-Key required. Unknown fields rejected. Replays recheck current authorization and target relationships, return the original receipt, and do not reapply changes. Snippet content is stored without sending it. Prebuilt/system/author fields are read-only. Bulk categories require bulk or both scope. Duplicate requires snippets:read in addition to snippets:write and does not copy prebuilt designation. PATCH folderId null moves a snippet to the root. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentAssetSnippetUpdate"}}}}
      responses:
        '200':
          description: Authorized data or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input or unsupported content shape.
        '401':
          description: Missing or invalid credential.
        '403':
          description: Missing scope, stale approval, revoked authority or unsupported record grant.
        '404':
          description: Target unavailable in this location.
        '409':
          description: Conflicting idempotency request or folder deletion in progress.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "snippets:delete"
      x-seedly-standard-scope: "snippets:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteSnippet
      tags: [Content Assets]
      summary: "deleteSnippet"
      description: "A snippet bound to review requests also needs review-requests:send. Explicit location-wide Standard v2 operation approval or OAuth grant required. Legacy keys and own/team/selected-record grants cannot use these operations. Native location permissions apply; OAuth also revalidates the current user. No sending, document signing, workflow execution, or provider calls. Stable Idempotency-Key required. Unknown fields rejected. Replays recheck current authorization and target relationships, return the original receipt, and do not reapply changes. Snippet content is stored without sending it. Prebuilt/system/author fields are read-only. Bulk categories require bulk or both scope. Duplicate requires snippets:read in addition to snippets:write and does not copy prebuilt designation. PATCH folderId null moves a snippet to the root. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: Authorized data or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input or unsupported content shape.
        '401':
          description: Missing or invalid credential.
        '403':
          description: Missing scope, stale approval, revoked authority or unsupported record grant.
        '404':
          description: Target unavailable in this location.
        '409':
          description: Conflicting idempotency request or folder deletion in progress.
        '429':
          description: Rate limit exceeded.
  /api/v1/snippets/{id}/duplicate:
    post:
      x-seedly-oauth-scope: "snippets:write"
      x-seedly-standard-scope: "snippets:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: duplicateSnippet
      tags: [Content Assets]
      summary: "duplicateSnippet"
      description: "Explicit location-wide Standard v2 operation approval or OAuth grant required. Legacy keys and own/team/selected-record grants cannot use these operations. Native location permissions apply; OAuth also revalidates the current user. No sending, document signing, workflow execution, or provider calls. Stable Idempotency-Key required. Unknown fields rejected. Replays recheck current authorization and target relationships, return the original receipt, and do not reapply changes. Snippet content is stored without sending it. Prebuilt/system/author fields are read-only. Bulk categories require bulk or both scope. Duplicate requires snippets:read in addition to snippets:write and does not copy prebuilt designation. PATCH folderId null moves a snippet to the root. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":100}}}}}}
      responses:
        '200':
          description: Authorized data or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input or unsupported content shape.
        '401':
          description: Missing or invalid credential.
        '403':
          description: Missing scope, stale approval, revoked authority or unsupported record grant.
        '404':
          description: Target unavailable in this location.
        '409':
          description: Conflicting idempotency request or folder deletion in progress.
        '429':
          description: Rate limit exceeded.
  /api/v1/content-library:
    get:
      x-seedly-oauth-scope: "documents:read"
      x-seedly-standard-scope: "documents:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listContentLibrary
      tags: [Content Assets]
      summary: "listContentLibrary"
      description: "Explicit location-wide Standard v2 operation approval or OAuth grant required. Legacy keys and own/team/selected-record grants cannot use these operations. Native location permissions apply; OAuth also revalidates the current user. No sending, document signing, workflow execution, or provider calls. Library blocks are limited to heading, text, divider, spacer, table_of_contents and content_table, with at most 100 blocks and 128 KiB serialized blocks. Rich text is sanitized with the strict profile; embedded media is removed. Media, interactive/pricing/signature and extension blocks are not yet supported. Existing richtext/paragraph/toc aliases are read without renaming; legacy plain text remains plain text. Existing unsupported block families cannot be fetched through this detail contract. Pages scan at most 50 rows, default 25. Eligibility filters may produce empty pages; follow meta.cursor while hasMore is true. Cursors are bound to the principal, location, collection and filters. "
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}},{"name":"category","in":"query","schema":{"type":"string"}},{"name":"search","in":"query","description":"Search by product name, up to 200 characters.","schema":{"type":"string","maxLength":200}}]
      responses:
        '200':
          description: Authorized data or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid input or unsupported content shape.
        '401':
          description: Missing or invalid credential.
        '403':
          description: Missing scope, stale approval, revoked authority or unsupported record grant.
        '404':
          description: Target unavailable in this location.
        '409':
          description: Conflicting idempotency request or folder deletion in progress.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "documents:write"
      x-seedly-standard-scope: "documents:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createContentLibrary
      tags: [Content Assets]
      summary: "createContentLibrary"
      description: "Explicit location-wide Standard v2 operation approval or OAuth grant required. Legacy keys and own/team/selected-record grants cannot use these operations. Native location permissions apply; OAuth also revalidates the current user. No sending, document signing, workflow execution, or provider calls. Stable Idempotency-Key required. Unknown fields rejected. Replays recheck current authorization and target relationships, return the original receipt, and do not reapply changes. Library blocks are limited to heading, text, divider, spacer, table_of_contents and content_table, with at most 100 blocks and 128 KiB serialized blocks. Rich text is sanitized with the strict profile; embedded media is removed. Media, interactive/pricing/signature and extension blocks are not yet supported. Existing richtext/paragraph/toc aliases are read without renaming; legacy plain text remains plain text. Existing unsupported block families cannot be fetched through this detail contract. "
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentAssetLibraryCreate"}}}}
      responses:
        '200':
          description: Authorized data or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input or unsupported content shape.
        '401':
          description: Missing or invalid credential.
        '403':
          description: Missing scope, stale approval, revoked authority or unsupported record grant.
        '404':
          description: Target unavailable in this location.
        '409':
          description: Conflicting idempotency request or folder deletion in progress.
        '429':
          description: Rate limit exceeded.
  /api/v1/content-library/{id}:
    get:
      x-seedly-oauth-scope: "documents:read"
      x-seedly-standard-scope: "documents:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getContentLibrary
      tags: [Content Assets]
      summary: "getContentLibrary"
      description: "Explicit location-wide Standard v2 operation approval or OAuth grant required. Legacy keys and own/team/selected-record grants cannot use these operations. Native location permissions apply; OAuth also revalidates the current user. No sending, document signing, workflow execution, or provider calls. Library blocks are limited to heading, text, divider, spacer, table_of_contents and content_table, with at most 100 blocks and 128 KiB serialized blocks. Rich text is sanitized with the strict profile; embedded media is removed. Media, interactive/pricing/signature and extension blocks are not yet supported. Existing richtext/paragraph/toc aliases are read without renaming; legacy plain text remains plain text. Existing unsupported block families cannot be fetched through this detail contract. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized data or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input or unsupported content shape.
        '401':
          description: Missing or invalid credential.
        '403':
          description: Missing scope, stale approval, revoked authority or unsupported record grant.
        '404':
          description: Target unavailable in this location.
        '409':
          description: Conflicting idempotency request or folder deletion in progress.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "documents:write"
      x-seedly-standard-scope: "documents:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateContentLibrary
      tags: [Content Assets]
      summary: "updateContentLibrary"
      description: "Explicit location-wide Standard v2 operation approval or OAuth grant required. Legacy keys and own/team/selected-record grants cannot use these operations. Native location permissions apply; OAuth also revalidates the current user. No sending, document signing, workflow execution, or provider calls. Stable Idempotency-Key required. Unknown fields rejected. Replays recheck current authorization and target relationships, return the original receipt, and do not reapply changes. Library blocks are limited to heading, text, divider, spacer, table_of_contents and content_table, with at most 100 blocks and 128 KiB serialized blocks. Rich text is sanitized with the strict profile; embedded media is removed. Media, interactive/pricing/signature and extension blocks are not yet supported. Existing richtext/paragraph/toc aliases are read without renaming; legacy plain text remains plain text. Existing unsupported block families cannot be fetched through this detail contract. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentAssetLibraryUpdate"}}}}
      responses:
        '200':
          description: Authorized data or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input or unsupported content shape.
        '401':
          description: Missing or invalid credential.
        '403':
          description: Missing scope, stale approval, revoked authority or unsupported record grant.
        '404':
          description: Target unavailable in this location.
        '409':
          description: Conflicting idempotency request or folder deletion in progress.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "documents:delete"
      x-seedly-standard-scope: "documents:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteContentLibrary
      tags: [Content Assets]
      summary: "deleteContentLibrary"
      description: "Explicit location-wide Standard v2 operation approval or OAuth grant required. Legacy keys and own/team/selected-record grants cannot use these operations. Native location permissions apply; OAuth also revalidates the current user. No sending, document signing, workflow execution, or provider calls. Stable Idempotency-Key required. Unknown fields rejected. Replays recheck current authorization and target relationships, return the original receipt, and do not reapply changes. Library blocks are limited to heading, text, divider, spacer, table_of_contents and content_table, with at most 100 blocks and 128 KiB serialized blocks. Rich text is sanitized with the strict profile; embedded media is removed. Media, interactive/pricing/signature and extension blocks are not yet supported. Existing richtext/paragraph/toc aliases are read without renaming; legacy plain text remains plain text. Existing unsupported block families cannot be fetched through this detail contract. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: Authorized data or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input or unsupported content shape.
        '401':
          description: Missing or invalid credential.
        '403':
          description: Missing scope, stale approval, revoked authority or unsupported record grant.
        '404':
          description: Target unavailable in this location.
        '409':
          description: Conflicting idempotency request or folder deletion in progress.
        '429':
          description: Rate limit exceeded.
  /api/v1/snippet-folders:
    get:
      x-seedly-oauth-scope: "snippets:read"
      x-seedly-standard-scope: "snippets:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listSnippetFolders
      tags: [Content Assets]
      summary: "listSnippetFolders"
      description: "Explicit location-wide Standard v2 operation approval or OAuth grant required. Legacy keys and own/team/selected-record grants cannot use these operations. Native location permissions apply; OAuth also revalidates the current user. No sending, document signing, workflow execution, or provider calls. Folder deletion is an asynchronous operation that moves immediate snippets and child folders to the root, then removes only the requested folder. New attachments are fenced while deletion runs. Poll the owner-bound deletion status; resume paused/stalled jobs with current authority or cancel to release the folder. Cancellation preserves already moved items and does not roll them back. Native operators with location-wide conversations delete permission can recover a revoked owner job from the snippet folder screen. Pages scan at most 50 rows, default 25. Eligibility filters may produce empty pages; follow meta.cursor while hasMore is true. Cursors are bound to the principal, location, collection and filters. "
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}}]
      responses:
        '200':
          description: Authorized data or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid input or unsupported content shape.
        '401':
          description: Missing or invalid credential.
        '403':
          description: Missing scope, stale approval, revoked authority or unsupported record grant.
        '404':
          description: Target unavailable in this location.
        '409':
          description: Conflicting idempotency request or folder deletion in progress.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "snippets:write"
      x-seedly-standard-scope: "snippets:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createSnippetFolder
      tags: [Content Assets]
      summary: "createSnippetFolder"
      description: "Explicit location-wide Standard v2 operation approval or OAuth grant required. Legacy keys and own/team/selected-record grants cannot use these operations. Native location permissions apply; OAuth also revalidates the current user. No sending, document signing, workflow execution, or provider calls. Stable Idempotency-Key required. Unknown fields rejected. Replays recheck current authorization and target relationships, return the original receipt, and do not reapply changes. Folder deletion is an asynchronous operation that moves immediate snippets and child folders to the root, then removes only the requested folder. New attachments are fenced while deletion runs. Poll the owner-bound deletion status; resume paused/stalled jobs with current authority or cancel to release the folder. Cancellation preserves already moved items and does not roll them back. Native operators with location-wide conversations delete permission can recover a revoked owner job from the snippet folder screen. "
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentAssetFolderCreate"}}}}
      responses:
        '200':
          description: Authorized data or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input or unsupported content shape.
        '401':
          description: Missing or invalid credential.
        '403':
          description: Missing scope, stale approval, revoked authority or unsupported record grant.
        '404':
          description: Target unavailable in this location.
        '409':
          description: Conflicting idempotency request or folder deletion in progress.
        '429':
          description: Rate limit exceeded.
  /api/v1/snippet-folders/{id}:
    get:
      x-seedly-oauth-scope: "snippets:read"
      x-seedly-standard-scope: "snippets:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getSnippetFolder
      tags: [Content Assets]
      summary: "getSnippetFolder"
      description: "Explicit location-wide Standard v2 operation approval or OAuth grant required. Legacy keys and own/team/selected-record grants cannot use these operations. Native location permissions apply; OAuth also revalidates the current user. No sending, document signing, workflow execution, or provider calls. Folder deletion is an asynchronous operation that moves immediate snippets and child folders to the root, then removes only the requested folder. New attachments are fenced while deletion runs. Poll the owner-bound deletion status; resume paused/stalled jobs with current authority or cancel to release the folder. Cancellation preserves already moved items and does not roll them back. Native operators with location-wide conversations delete permission can recover a revoked owner job from the snippet folder screen. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized data or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input or unsupported content shape.
        '401':
          description: Missing or invalid credential.
        '403':
          description: Missing scope, stale approval, revoked authority or unsupported record grant.
        '404':
          description: Target unavailable in this location.
        '409':
          description: Conflicting idempotency request or folder deletion in progress.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "snippets:write"
      x-seedly-standard-scope: "snippets:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateSnippetFolder
      tags: [Content Assets]
      summary: "updateSnippetFolder"
      description: "Explicit location-wide Standard v2 operation approval or OAuth grant required. Legacy keys and own/team/selected-record grants cannot use these operations. Native location permissions apply; OAuth also revalidates the current user. No sending, document signing, workflow execution, or provider calls. Stable Idempotency-Key required. Unknown fields rejected. Replays recheck current authorization and target relationships, return the original receipt, and do not reapply changes. Folder deletion is an asynchronous operation that moves immediate snippets and child folders to the root, then removes only the requested folder. New attachments are fenced while deletion runs. Poll the owner-bound deletion status; resume paused/stalled jobs with current authority or cancel to release the folder. Cancellation preserves already moved items and does not roll them back. Native operators with location-wide conversations delete permission can recover a revoked owner job from the snippet folder screen. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentAssetFolderUpdate"}}}}
      responses:
        '200':
          description: Authorized data or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input or unsupported content shape.
        '401':
          description: Missing or invalid credential.
        '403':
          description: Missing scope, stale approval, revoked authority or unsupported record grant.
        '404':
          description: Target unavailable in this location.
        '409':
          description: Conflicting idempotency request or folder deletion in progress.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "snippets:delete"
      x-seedly-standard-scope: "snippets:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteSnippetFolder
      tags: [Content Assets]
      summary: "deleteSnippetFolder"
      description: "Explicit location-wide Standard v2 operation approval or OAuth grant required. Legacy keys and own/team/selected-record grants cannot use these operations. Native location permissions apply; OAuth also revalidates the current user. No sending, document signing, workflow execution, or provider calls. Stable Idempotency-Key required. Unknown fields rejected. Replays recheck current authorization and target relationships, return the original receipt, and do not reapply changes. Folder deletion is an asynchronous operation that moves immediate snippets and child folders to the root, then removes only the requested folder. New attachments are fenced while deletion runs. Poll the owner-bound deletion status; resume paused/stalled jobs with current authority or cancel to release the folder. Cancellation preserves already moved items and does not roll them back. Native operators with location-wide conversations delete permission can recover a revoked owner job from the snippet folder screen. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses:
        '200':
          description: Authorized data or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input or unsupported content shape.
        '401':
          description: Missing or invalid credential.
        '403':
          description: Missing scope, stale approval, revoked authority or unsupported record grant.
        '404':
          description: Target unavailable in this location.
        '409':
          description: Conflicting idempotency request or folder deletion in progress.
        '429':
          description: Rate limit exceeded.
  /api/v1/snippet-folder-deletions/{id}:
    get:
      x-seedly-oauth-scope: "snippets:delete"
      x-seedly-standard-scope: "snippets:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getSnippetFolderDeletion
      tags: [Content Assets]
      summary: "getSnippetFolderDeletion"
      description: "Explicit location-wide Standard v2 operation approval or OAuth grant required. Legacy keys and own/team/selected-record grants cannot use these operations. Native location permissions apply; OAuth also revalidates the current user. No sending, document signing, workflow execution, or provider calls. Folder deletion is an asynchronous operation that moves immediate snippets and child folders to the root, then removes only the requested folder. New attachments are fenced while deletion runs. Poll the owner-bound deletion status; resume paused/stalled jobs with current authority or cancel to release the folder. Cancellation preserves already moved items and does not roll them back. Native operators with location-wide conversations delete permission can recover a revoked owner job from the snippet folder screen. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized data or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input or unsupported content shape.
        '401':
          description: Missing or invalid credential.
        '403':
          description: Missing scope, stale approval, revoked authority or unsupported record grant.
        '404':
          description: Target unavailable in this location.
        '409':
          description: Conflicting idempotency request or folder deletion in progress.
        '429':
          description: Rate limit exceeded.
  /api/v1/snippet-folder-deletions/{id}/resume:
    post:
      x-seedly-oauth-scope: "snippets:delete"
      x-seedly-standard-scope: "snippets:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: resumeSnippetFolderDeletion
      tags: [Content Assets]
      summary: "resumeSnippetFolderDeletion"
      description: "Explicit location-wide Standard v2 operation approval or OAuth grant required. Legacy keys and own/team/selected-record grants cannot use these operations. Native location permissions apply; OAuth also revalidates the current user. No sending, document signing, workflow execution, or provider calls. Stable Idempotency-Key required. Unknown fields rejected. Replays recheck current authorization and target relationships, return the original receipt, and do not reapply changes. Folder deletion is an asynchronous operation that moves immediate snippets and child folders to the root, then removes only the requested folder. New attachments are fenced while deletion runs. Poll the owner-bound deletion status; resume paused/stalled jobs with current authority or cancel to release the folder. Cancellation preserves already moved items and does not roll them back. Native operators with location-wide conversations delete permission can recover a revoked owner job from the snippet folder screen. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
      responses:
        '200':
          description: Authorized data or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input or unsupported content shape.
        '401':
          description: Missing or invalid credential.
        '403':
          description: Missing scope, stale approval, revoked authority or unsupported record grant.
        '404':
          description: Target unavailable in this location.
        '409':
          description: Conflicting idempotency request or folder deletion in progress.
        '429':
          description: Rate limit exceeded.
  /api/v1/snippet-folder-deletions/{id}/cancel:
    post:
      x-seedly-oauth-scope: "snippets:delete"
      x-seedly-standard-scope: "snippets:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: cancelSnippetFolderDeletion
      tags: [Content Assets]
      summary: "cancelSnippetFolderDeletion"
      description: "Explicit location-wide Standard v2 operation approval or OAuth grant required. Legacy keys and own/team/selected-record grants cannot use these operations. Native location permissions apply; OAuth also revalidates the current user. No sending, document signing, workflow execution, or provider calls. Stable Idempotency-Key required. Unknown fields rejected. Replays recheck current authorization and target relationships, return the original receipt, and do not reapply changes. Folder deletion is an asynchronous operation that moves immediate snippets and child folders to the root, then removes only the requested folder. New attachments are fenced while deletion runs. Poll the owner-bound deletion status; resume paused/stalled jobs with current authority or cancel to release the folder. Cancellation preserves already moved items and does not roll them back. Native operators with location-wide conversations delete permission can recover a revoked owner job from the snippet folder screen. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}}
      responses:
        '200':
          description: Authorized data or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input or unsupported content shape.
        '401':
          description: Missing or invalid credential.
        '403':
          description: Missing scope, stale approval, revoked authority or unsupported record grant.
        '404':
          description: Target unavailable in this location.
        '409':
          description: Conflicting idempotency request or folder deletion in progress.
        '429':
          description: Rate limit exceeded.
  /api/v1/products:
    get:
      x-seedly-oauth-scope: "products:read"
      x-seedly-standard-scope: "products:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listIntegrationProducts
      tags: [Content Assets]
      summary: List active product metadata
      description: "Requires explicitly approved location-wide products:read, native invoices view/all authority, and current OAuth role/token ceiling. Legacy and own/team/selected grants are denied. Returns catalog price in major currency units and metadata only, without images, provider IDs, author information, configuration or cost data. Detail may show an inactive product; referenced content requires active products. List scans at most 50 rows, default 25, and may return empty pages after active/tenant filtering; follow meta.cursor. No product, invoice, billing or provider mutation."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}}]
      responses:
        '200':
          description: Authorized catalog metadata.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/IntegrationCatalogProduct"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Product unavailable in this location.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "products:write"
      x-seedly-standard-scope: "products:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createProductRecord
      tags: [Commerce Catalog]
      summary: "Create a product"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Product price is stored and returned in major currency units, for example 19.99 means 19.99 of the currency. No provider call, billing or invoice mutation occurs."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name","price"],"properties":{"name":{"type":"string","maxLength":255},"description":{"type":"string","maxLength":5000},"price":{"type":"number","minimum":0,"maximum":1000000000,"description":"Major currency units."},"currency":{"type":"string","pattern":"^[A-Z]{3}$","description":"Defaults to USD on create."},"sku":{"type":"string","maxLength":100},"category":{"type":"string","maxLength":255},"taxCategory":{"type":"string","maxLength":255}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/products/{id}:
    get:
      x-seedly-oauth-scope: "products:read"
      x-seedly-standard-scope: "products:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getIntegrationProduct
      tags: [Content Assets]
      summary: Read product metadata
      description: "Requires explicitly approved location-wide products:read, native invoices view/all authority, and current OAuth role/token ceiling. Legacy and own/team/selected grants are denied. Returns catalog price in major currency units and metadata only, without images, provider IDs, author information, configuration or cost data. Detail may show an inactive product; referenced content requires active products. List scans at most 50 rows, default 25, and may return empty pages after active/tenant filtering; follow meta.cursor. No product, invoice, billing or provider mutation."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized catalog metadata.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/IntegrationCatalogProduct"}}}}}
        '400':
          description: Invalid parameters.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Product unavailable in this location.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "products:write"
      x-seedly-standard-scope: "products:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateProductRecord
      tags: [Commerce Catalog]
      summary: "Update a product"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Product price is stored and returned in major currency units, for example 19.99 means 19.99 of the currency. Changing a catalog price never rewrites negotiated prices already stored on invoices, estimates or content blocks. No provider call, billing or invoice mutation occurs."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":255},"description":{"type":"string","maxLength":5000},"price":{"type":"number","minimum":0,"maximum":1000000000,"description":"Major currency units."},"currency":{"type":"string","pattern":"^[A-Z]{3}$","description":"Defaults to USD on create."},"sku":{"type":"string","maxLength":100},"category":{"type":"string","maxLength":255},"taxCategory":{"type":"string","maxLength":255},"isActive":{"type":"boolean"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "products:delete"
      x-seedly-standard-scope: "products:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteProductRecord
      tags: [Commerce Catalog]
      summary: "Deactivate a product"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. This is the native soft delete: the product becomes inactive and stays readable through product records. Reusable content that references it then fails its active-product proof. No provider call, billing or invoice mutation occurs."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/products/{id}/image:
    put:
      x-seedly-oauth-scope: "products:write"
      x-seedly-standard-scope: "products:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: setProductImage
      tags: [Commerce Catalog]
      summary: "Set or clear a product image"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. fileId is a files record in this location, or null to clear. Also needs the exact file read approval, and the file must be an image. No storage URL is written on the product. Read the image bytes through the file content route. The product scope alone cannot attach a file."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","required":["fileId"],"additionalProperties":false,"properties":{"fileId":{"type":["string","null"]}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/product-catalog-jobs:
    post:
      x-seedly-oauth-scope: "products:write"
      x-seedly-standard-scope: "products:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: startProductCatalogJob
      tags: [Commerce Catalog]
      summary: "Start a durable category rename or SKU duplicate"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. For catalogs above the synchronous ceiling of 500 rows or 2 MiB. type category_rename takes id and name and may take description. type product_duplicate takes id. A rename changes the category row at once and then updates products in batches; products show the old name until their batch runs. Each batch rechecks this credential and its token ceiling. Returns the job id. At most 3 running jobs per location and one per record."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","required":["type","id"],"additionalProperties":false,"properties":{"type":{"type":"string","enum":["category_rename","product_duplicate"]},"id":{"type":"string"},"name":{"type":"string","maxLength":255},"description":{"type":"string","maxLength":5000}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/product-catalog-jobs/{id}:
    get:
      x-seedly-oauth-scope: "products:read"
      x-seedly-standard-scope: "products:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getProductCatalogJob
      tags: [Commerce Catalog]
      summary: "Read a catalog job"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Only the credential that started the job can read it. status is running, paused, cancelled or complete. failedIds lists at most 100 rows that could not change. partial means some changes were made and the job did not finish; finished batches are not rolled back. resultId is the new product of a finished duplicate."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/product-catalog-jobs/{id}/cancel:
    post:
      x-seedly-oauth-scope: "products:write"
      x-seedly-standard-scope: "products:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: cancelProductCatalogJob
      tags: [Commerce Catalog]
      summary: "Cancel a catalog job"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Stops later batches. Finished batches stay in place. Only the credential that started the job can cancel it."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/product-catalog-jobs/{id}/resume:
    post:
      x-seedly-oauth-scope: "products:write"
      x-seedly-standard-scope: "products:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: resumeProductCatalogJob
      tags: [Commerce Catalog]
      summary: "Resume a catalog job"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Continues a paused, cancelled or stalled job with this credential's current authority. Refused if the record changed, if the job has been idle for 24 hours, or if it is older than 72 hours. Failed rows are rescanned from the start."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/product-catalog-deletion-jobs:
    post:
      x-seedly-oauth-scope: "products:delete"
      x-seedly-standard-scope: "products:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: startProductCatalogDeletionJob
      tags: [Commerce Catalog]
      summary: "Start a durable category or folder deletion"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. For catalogs above the synchronous ceiling of 500 rows or 2 MiB. type category_delete clears the category on its products. type folder_delete moves its products and child folders to the root. The category or folder is deleted only after every row has changed. Each batch rechecks this credential and its token ceiling."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","required":["type","id"],"additionalProperties":false,"properties":{"type":{"type":"string","enum":["category_delete","folder_delete"]},"id":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/product-catalog-deletion-jobs/{id}:
    get:
      x-seedly-oauth-scope: "products:read"
      x-seedly-standard-scope: "products:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getProductCatalogDeletionJob
      tags: [Commerce Catalog]
      summary: "Read a catalog deletion job"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Only the credential that started the job can read it. Reports the same fields as a catalog job."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/product-catalog-deletion-jobs/{id}/cancel:
    post:
      x-seedly-oauth-scope: "products:delete"
      x-seedly-standard-scope: "products:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: cancelProductCatalogDeletionJob
      tags: [Commerce Catalog]
      summary: "Cancel a catalog deletion job"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Stops later batches. Finished batches stay in place and the category or folder is kept."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/product-catalog-deletion-jobs/{id}/resume:
    post:
      x-seedly-oauth-scope: "products:delete"
      x-seedly-standard-scope: "products:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: resumeProductCatalogDeletionJob
      tags: [Commerce Catalog]
      summary: "Resume a catalog deletion job"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Continues a paused or stalled job. A cancelled deletion cannot resume: start a new job. It uses this credential's current authority. Refused if the record changed, if the job has been idle for 24 hours, or if it is older than 72 hours."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/product-records:
    get:
      x-seedly-oauth-scope: "products:read"
      x-seedly-standard-scope: "products:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listProductRecords
      tags: [Commerce Catalog]
      summary: "List product administration records"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Product price is stored and returned in major currency units, for example 19.99 means 19.99 of the currency. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor. Includes inactive products on request and folder and tax-category metadata. imageFileId appears only with the exact file read approval. Provider identifiers, storage URLs and author identities are never returned."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}},{"name":"includeInactive","in":"query","schema":{"type":"boolean"}},{"name":"folderId","in":"query","schema":{"type":"string"}},{"name":"category","in":"query","schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/product-records/{id}:
    get:
      x-seedly-oauth-scope: "products:read"
      x-seedly-standard-scope: "products:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getProductRecord
      tags: [Commerce Catalog]
      summary: "Read a product administration record"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Product price is stored and returned in major currency units, for example 19.99 means 19.99 of the currency. imageFileId appears only with the exact file read approval. Provider identifiers, storage URLs and author identities are never returned."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/products/{id}/duplicate:
    post:
      x-seedly-oauth-scope: "products:write"
      x-seedly-standard-scope: "products:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: duplicateProductRecord
      tags: [Commerce Catalog]
      summary: "Duplicate a product"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Synchronous work is capped at 500 rows and 2 MiB of native reads; larger locations receive 409 and should use the dashboard. A SKU receives the next native numeric suffix. No provider call, billing or invoice mutation occurs."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/products/{id}/folder:
    put:
      x-seedly-oauth-scope: "products:write"
      x-seedly-standard-scope: "products:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: moveProductRecord
      tags: [Commerce Catalog]
      summary: "Move a product to a folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["folderId"],"properties":{"folderId":{"type":["string","null"],"description":"Null moves the product to the root."}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/product-folders:
    get:
      x-seedly-oauth-scope: "products:read"
      x-seedly-standard-scope: "products:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listProductFolders
      tags: [Commerce Catalog]
      summary: "List product folders"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "products:write"
      x-seedly-standard-scope: "products:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createProductFolder
      tags: [Commerce Catalog]
      summary: "Create a product folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Synchronous work is capped at 500 rows and 2 MiB of native reads; larger locations receive 409 and should use the dashboard."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string","maxLength":255},"parentId":{"type":["string","null"]}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/product-folders/{id}:
    patch:
      x-seedly-oauth-scope: "products:write"
      x-seedly-standard-scope: "products:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateProductFolder
      tags: [Commerce Catalog]
      summary: "Rename a product folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string","maxLength":255}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "products:delete"
      x-seedly-standard-scope: "products:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteProductFolder
      tags: [Commerce Catalog]
      summary: "Delete a product folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Synchronous work is capped at 500 rows and 2 MiB of native reads; larger locations receive 409 and should use the dashboard. Contained products and child folders move to the root."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/product-categories:
    get:
      x-seedly-oauth-scope: "products:read"
      x-seedly-standard-scope: "products:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listProductCategories
      tags: [Commerce Catalog]
      summary: "List product categories"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "products:write"
      x-seedly-standard-scope: "products:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createProductCategory
      tags: [Commerce Catalog]
      summary: "Create a product category"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Synchronous work is capped at 500 rows and 2 MiB of native reads; larger locations receive 409 and should use the dashboard."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string","maxLength":255},"description":{"type":"string","maxLength":5000}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/product-categories/{id}:
    patch:
      x-seedly-oauth-scope: "products:write"
      x-seedly-standard-scope: "products:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateProductCategory
      tags: [Commerce Catalog]
      summary: "Update a product category"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Synchronous work is capped at 500 rows and 2 MiB of native reads; larger locations receive 409 and should use the dashboard. A rename updates every product in the category."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":255},"description":{"type":"string","maxLength":5000}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "products:delete"
      x-seedly-standard-scope: "products:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteProductCategory
      tags: [Commerce Catalog]
      summary: "Delete a product category"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Synchronous work is capped at 500 rows and 2 MiB of native reads; larger locations receive 409 and should use the dashboard. Products in the category become uncategorized."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/product-bundles:
    get:
      x-seedly-oauth-scope: "products:read"
      x-seedly-standard-scope: "products:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listProductBundles
      tags: [Commerce Catalog]
      summary: "List product bundles"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor. bundlePrice is in major currency units. Members are returned as product IDs."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "products:write"
      x-seedly-standard-scope: "products:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createProductBundle
      tags: [Commerce Catalog]
      summary: "Create a product bundle"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. At most 100 same-location products."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name","productIds"],"properties":{"name":{"type":"string","maxLength":255},"description":{"type":"string","maxLength":5000},"productIds":{"type":"array","maxItems":100,"items":{"type":"string"}},"bundlePrice":{"type":"number","minimum":0,"maximum":1000000000,"description":"Major currency units; omit to sum products."}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/product-bundles/{id}:
    get:
      x-seedly-oauth-scope: "products:read"
      x-seedly-standard-scope: "products:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getProductBundle
      tags: [Commerce Catalog]
      summary: "Read a product bundle"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. bundlePrice is in major currency units."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "products:write"
      x-seedly-standard-scope: "products:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateProductBundle
      tags: [Commerce Catalog]
      summary: "Update a product bundle"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. At most 100 same-location products."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":255},"description":{"type":"string","maxLength":5000},"productIds":{"type":"array","maxItems":100,"items":{"type":"string"}},"bundlePrice":{"type":"number","minimum":0,"maximum":1000000000,"description":"Major currency units; omit to sum products."},"isActive":{"type":"boolean"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "products:delete"
      x-seedly-standard-scope: "products:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteProductBundle
      tags: [Commerce Catalog]
      summary: "Delete a product bundle"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Permanently removes the bundle, not its products."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/product-dependencies:
    get:
      x-seedly-oauth-scope: "products:read"
      x-seedly-standard-scope: "products:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listProductDependencies
      tags: [Commerce Catalog]
      summary: "List dependencies for a product"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}},{"name":"productId","in":"query","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "products:write"
      x-seedly-standard-scope: "products:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createProductDependency
      tags: [Commerce Catalog]
      summary: "Create a product dependency"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["productId","requiresProductId","type"],"properties":{"productId":{"type":"string"},"requiresProductId":{"type":"string"},"type":{"type":"string","enum":["requires","excludes","recommends"]}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/product-dependencies/{id}:
    delete:
      x-seedly-oauth-scope: "products:delete"
      x-seedly-standard-scope: "products:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteProductDependency
      tags: [Commerce Catalog]
      summary: "Delete a product dependency"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/discount-codes:
    get:
      x-seedly-oauth-scope: "discounts:read"
      x-seedly-standard-scope: "discounts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listDiscountCodes
      tags: [Commerce Catalog]
      summary: "List discount codes"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor. Returns redeemable code values. value is a percentage from 0 to 100 or a fixed amount in major currency units. Dates are Unix milliseconds."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "discounts:write"
      x-seedly-standard-scope: "discounts:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createDiscountCode
      tags: [Commerce Catalog]
      summary: "Create a discount code"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["code","type","value"],"properties":{"code":{"type":"string","maxLength":64,"pattern":"^[A-Za-z0-9_-]+$","description":"Stored uppercase."},"type":{"type":"string","enum":["percentage","fixed"]},"value":{"type":"number","minimum":0,"description":"Percentage from 0 to 100, or a fixed amount in major currency units."},"maxUses":{"type":"integer","minimum":0},"maxUsesPerCustomer":{"type":"integer","minimum":0},"validFrom":{"type":"integer","description":"Unix milliseconds."},"validUntil":{"type":"integer","description":"Unix milliseconds."},"isActive":{"type":"boolean"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/discount-codes/{id}:
    get:
      x-seedly-oauth-scope: "discounts:read"
      x-seedly-standard-scope: "discounts:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getDiscountCode
      tags: [Commerce Catalog]
      summary: "Read a discount code"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. value is a percentage from 0 to 100 or a fixed amount in major currency units. Dates are Unix milliseconds."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "discounts:write"
      x-seedly-standard-scope: "discounts:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateDiscountCode
      tags: [Commerce Catalog]
      summary: "Update a discount code"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"code":{"type":"string","maxLength":64,"pattern":"^[A-Za-z0-9_-]+$","description":"Stored uppercase."},"type":{"type":"string","enum":["percentage","fixed"]},"value":{"type":"number","minimum":0,"description":"Percentage from 0 to 100, or a fixed amount in major currency units."},"maxUses":{"type":"integer","minimum":0},"maxUsesPerCustomer":{"type":"integer","minimum":0},"validFrom":{"type":"integer","description":"Unix milliseconds."},"validUntil":{"type":"integer","description":"Unix milliseconds."},"isActive":{"type":"boolean"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "discounts:write"
      x-seedly-standard-scope: "discounts:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteDiscountCode
      tags: [Commerce Catalog]
      summary: "Delete a discount code"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Estimates that already applied the code keep their stored discount."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/file-uploads:
    post:
      x-seedly-oauth-scope: "files:write"
      x-seedly-standard-scope: "files:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createFileUpload
      tags: [Files]
      summary: "Start a multipart file upload"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. For files above the 20 MiB limit of POST /api/v1/files. sizeBytes is the whole file in bytes; sha256 is its lowercase hex digest. Purpose caps apply to the whole file: attachment and import 50 MiB, form-upload 25 MiB, avatar 5 MiB. The response gives partBytes (16 MiB) and partCount. An upload expires after 24 hours and its parts are removed. entityType and entityId need the exact read approval of that record family."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","required":["filename","contentType","sizeBytes","sha256"],"additionalProperties":false,"properties":{"filename":{"type":"string","maxLength":255},"contentType":{"type":"string"},"sizeBytes":{"type":"integer","minimum":1},"sha256":{"type":"string","pattern":"^[0-9a-f]{64}$"},"purpose":{"type":"string","enum":["attachment","avatar","form-upload","import"]},"entityType":{"type":"string"},"entityId":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/file-uploads/{id}:
    delete:
      x-seedly-oauth-scope: "files:write"
      x-seedly-standard-scope: "files:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: abortFileUpload
      tags: [Files]
      summary: "Abort a multipart upload"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Removes the uploaded parts. A completed upload cannot be aborted. Only the credential that started it can abort it."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    get:
      x-seedly-oauth-scope: "files:read"
      x-seedly-standard-scope: "files:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getFileUpload
      tags: [Files]
      summary: "Read a multipart upload"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Only the credential that started the upload can read it. receivedParts lists accepted part indexes. fileId is set when complete."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/file-uploads/{id}/parts:
    put:
      x-seedly-oauth-scope: "files:write"
      x-seedly-standard-scope: "files:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: uploadFilePart
      tags: [Files]
      summary: "Upload one part"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Raw body. index is zero based. Every part is exactly partBytes except the last, which is the remainder. Authority, the file policy and the linked record are proved before bytes are stored and again after. A part cannot be replaced. Send a different Idempotency-Key for each part."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"index","in":"query","required":true,"schema":{"type":"integer","minimum":0}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/file-uploads/{id}/complete:
    post:
      x-seedly-oauth-scope: "files:write"
      x-seedly-standard-scope: "files:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: completeFileUpload
      tags: [Files]
      summary: "Join parts into a file"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Checks every part arrived, joins them, and compares the size and sha256 with the declaration. A mismatch returns 409 and creates no file. Returns the file id. The same native content validation as a direct upload then runs."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/files:
    get:
      x-seedly-oauth-scope: "files:read"
      x-seedly-standard-scope: "files:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listFiles
      tags: [Files]
      summary: "List files"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor. A file linked to a contact, conversation message, form or review is readable only with that record family exact read approval and a live same-location record. Files linked to any other record family stay hidden. Another mailbox private Gmail attachment is hidden. Filter with entityType and entityId together. Storage identifiers and uploader identities are never returned."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}},{"name":"entityType","in":"query","schema":{"type":"string"}},{"name":"entityId","in":"query","schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "files:write"
      x-seedly-standard-scope: "files:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: uploadFile
      tags: [Files]
      summary: "Upload and finalize a file"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. The request body is the raw file, at most 20 MiB and at most the native purpose limit, and Content-Type is the file type. filename is required as a query parameter. The native file-type allowlist, blocked extensions, filename sanitizing and asynchronous content validation apply, and a file that fails content validation is removed. Bytes are stored only after authority is proved; an accepted retry stores nothing. No upload URL is issued. A file linked to a contact, conversation message, form or review is readable only with that record family exact read approval and a live same-location record. Files linked to any other record family stay hidden. Another mailbox private Gmail attachment is hidden."
      parameters: [{"name":"filename","in":"query","required":true,"schema":{"type":"string"}},{"name":"purpose","in":"query","schema":{"type":"string"}},{"name":"entityType","in":"query","schema":{"type":"string"}},{"name":"entityId","in":"query","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/files/{id}:
    get:
      x-seedly-oauth-scope: "files:read"
      x-seedly-standard-scope: "files:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getFile
      tags: [Files]
      summary: "Read file metadata"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. A file linked to a contact, conversation message, form or review is readable only with that record family exact read approval and a live same-location record. Files linked to any other record family stay hidden. Another mailbox private Gmail attachment is hidden."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "files:delete"
      x-seedly-standard-scope: "files:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteFile
      tags: [Files]
      summary: "Delete a file"
      description: "A file that a message attachment, invoice, document, saved document version, estimate, invoice or document template, or saved content block references is refused with a conflict, however many records hold it. Deletes are also refused with a conflict until the location's file reference index for invoices and documents is complete. While the index for estimates, templates or saved blocks is still being built for a location, a file is checked against those records directly, and every file is refused with a conflict if the location holds more than 500 of one of them or 4 MiB in total; once built, the check does not depend on how many records the location holds. A file that a record in any other location or agency references, such as a template copied there by a snapshot clone, is also refused with a conflict that does not identify the record or its location, and every file is refused until the template and saved block index is complete in every location. Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Permanently deletes the record and its stored bytes. A file linked to a contact, conversation message, form or review is readable only with that record family exact read approval and a live same-location record. Files linked to any other record family stay hidden. Another mailbox private Gmail attachment is hidden."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/files/{id}/content:
    get:
      x-seedly-oauth-scope: "files:read"
      x-seedly-standard-scope: "files:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: downloadFile
      tags: [Files]
      summary: "Download file bytes"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Bytes are returned on this authenticated response as an attachment. No storage URL is issued, so access ends with the credential. A whole file response is at most 20 MiB. A larger file is read with one Range header per request, for example bytes=0-20971519, returning 206 with Content-Range. A range above 20 MiB is cut short, so read Content-Range and continue from there. Multiple ranges are refused. A file linked to a contact, conversation message, form or review is readable only with that record family exact read approval and a live same-location record. Files linked to any other record family stay hidden. Another mailbox private Gmail attachment is hidden."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Authenticated binary content; no storage URL is issued."
          content: {"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/files/{id}/link:
    put:
      x-seedly-oauth-scope: "files:write"
      x-seedly-standard-scope: "files:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: linkFile
      tags: [Files]
      summary: "Link a file to a record"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Requires exact read approval for both the current and new linked record family. A file linked to a contact, conversation message, form or review is readable only with that record family exact read approval and a live same-location record. Files linked to any other record family stay hidden. Another mailbox private Gmail attachment is hidden."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["entityType","entityId"],"properties":{"entityType":{"type":"string","enum":["contact","message","form"]},"entityId":{"type":"string","maxLength":64}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoices:
    get:
      x-seedly-oauth-scope: "invoices:read"
      x-seedly-standard-scope: "invoices:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listInvoices
      tags: [Invoices]
      summary: "List invoices"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor. All invoice money fields are major currency units, for example 19.99, exactly as stored. Totals are computed by the CRM from the line items; a client never supplies them. Customer tokens, provider identifiers, signature data and canvas content are never returned. A contactId filter requires exact contacts:read approval."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}},{"name":"status","in":"query","schema":{"type":"string"}},{"name":"contactId","in":"query","schema":{"type":"string"}},{"name":"folderId","in":"query","schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "invoices:write"
      x-seedly-standard-scope: "invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createInvoice
      tags: [Invoices]
      summary: "Create a draft invoice"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. All invoice money fields are major currency units, for example 19.99, exactly as stored. Totals are computed by the CRM from the line items; a client never supplies them. Native plan, numbering, default terms and tax behavior apply. Nothing is sent."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["items"],"properties":{"contactId":{"type":"string","description":"Requires exact contacts:read approval."},"items":{"type":"array","maxItems":500,"items":{"type":"object","required":["quantity","unitPrice"],"additionalProperties":false,"properties":{"description":{"type":"string","maxLength":5000},"quantity":{"type":"number","minimum":0},"unitPrice":{"type":"number","description":"Major currency units."},"productId":{"type":"string","description":"Requires exact products:read detail approval."},"taxable":{"type":"boolean"},"taxRate":{"type":"number","minimum":0,"maximum":100}}}},"taxes":{"type":"array","maxItems":20,"description":"Each rate is a percent from 0 to 100, for example 8.25, and is returned the same way.","items":{"type":"object","required":["name","rate"],"additionalProperties":false,"properties":{"name":{"type":"string"},"rate":{"type":"number","minimum":0,"maximum":100}}}},"taxInclusive":{"type":"boolean"},"discountType":{"type":"string","enum":["percentage","fixed"]},"discountValue":{"type":"number","minimum":0,"description":"A percent from 0 to 100, or a fixed amount in major currency units, by discountType."},"currency":{"type":"string","pattern":"^[A-Z]{3}$"},"dueDate":{"type":"integer","description":"Unix milliseconds."},"terms":{"type":"string"},"notes":{"type":"string"},"folderId":{"type":"string"},"templateId":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoices/from-opportunity:
    post:
      x-seedly-oauth-scope: "invoices:write"
      x-seedly-standard-scope: "invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createInvoiceFromOpportunity
      tags: [Invoices]
      summary: "Create a draft invoice from an opportunity"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. All invoice money fields are major currency units, for example 19.99, exactly as stored. Totals are computed by the CRM from the line items; a client never supplies them. Requires exact opportunities:read approval and, for OAuth, the current pipeline access."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["opportunityId"],"properties":{"opportunityId":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoices/lookup:
    get:
      x-seedly-oauth-scope: "invoices:read"
      x-seedly-standard-scope: "invoices:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getInvoiceByNumber
      tags: [Invoices]
      summary: "Find an invoice by its number"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Exact match on the number query parameter, such as INV-0001. Returns the invoice detail, or 404. Two rows with one number return 409. Amounts are major currency units."
      parameters: [{"name":"number","in":"query","required":true,"schema":{"type":"string","maxLength":100}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoices/{id}/canvas:
    put:
      x-seedly-oauth-scope: "invoices:write"
      x-seedly-standard-scope: "invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateInvoiceCanvas
      tags: [Invoices]
      summary: "Replace an invoice canvas"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Replaces blocks, pages or globalStyles; omitted ones stay. Blocks use the reviewed content shape: heading, text, divider, spacer, table_of_contents, content_table and terms, plus line_items with no rows, which shows the invoice's own items. HTML is sanitized and the result is checked. Images, video and field blocks are not writable. A stored block this API cannot show must be kept by sending {id, keep: true} in its place; a write that drops one returns 409. At most 100 blocks and 128 KiB a list, 20 pages and 256 KiB of pages. Send blocks or pages, not both; a record with pages takes pages. globalStyles takes color, font, margin and typography tokens. customCss is not writable and is kept. Priced blocks that hold their own prices are refused, because an invoice total never sees them. Native status rules apply. Any write on a non-draft invoice also needs exact invoices:send. A canvas with blocks needs a line_items block with no rows of its own, so the invoice's real rows stay on the page. columnHeaders takes fixed labels only: description (Description, Item, Items, Service, Services, Product, Details), quantity (Quantity, Qty, Hours, Units), unitPrice (Unit Price, Price, Rate, Unit Rate), amount (Amount, Total, Line Total)."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"blocks":{"type":"array","maxItems":100,"items":{"type":"object"}},"pages":{"type":"array","maxItems":20,"items":{"type":"object"}},"globalStyles":{"type":"object"},"columnHeaders":{"type":"object"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    get:
      x-seedly-oauth-scope: "invoices:read"
      x-seedly-standard-scope: "invoices:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getInvoiceCanvas
      tags: [Invoices]
      summary: "Read an invoice canvas"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Blocks in the reviewed shape are returned. Any other stored block is returned as {id, type, unsupported: true} so it can be kept on write."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoices/{id}:
    get:
      x-seedly-oauth-scope: "invoices:read"
      x-seedly-standard-scope: "invoices:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getInvoice
      tags: [Invoices]
      summary: "Read an invoice"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. All invoice money fields are major currency units, for example 19.99, exactly as stored. Totals are computed by the CRM from the line items; a client never supplies them. Customer tokens, provider identifiers, signature data and canvas content are never returned."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "invoices:write"
      x-seedly-standard-scope: "invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateInvoice
      tags: [Invoices]
      summary: "Update an invoice"
      description: "On a non-draft invoice every field except dealId needs exact invoices:send, because the customer already holds this document. Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. All invoice money fields are major currency units, for example 19.99, exactly as stored. Totals are computed by the CRM from the line items; a client never supplies them. The native status and amount-change rules apply, including expiring an existing payment link when the amount changes. On an issued invoice, changing dueDate or late-fee terms needs exact invoices:send approval, because the overdue job then charges fees and mails reminders. Editing a recurring master whose schedule auto-sends also needs it, and the schedule then answers to this credential."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"contactId":{"type":"string","description":"Requires exact contacts:read approval."},"items":{"type":"array","maxItems":500,"items":{"type":"object","required":["quantity","unitPrice"],"additionalProperties":false,"properties":{"description":{"type":"string","maxLength":5000},"quantity":{"type":"number","minimum":0},"unitPrice":{"type":"number","description":"Major currency units."},"productId":{"type":"string","description":"Requires exact products:read detail approval."},"taxable":{"type":"boolean"},"taxRate":{"type":"number","minimum":0,"maximum":100}}}},"taxes":{"type":"array","maxItems":20,"description":"Each rate is a percent from 0 to 100, for example 8.25, and is returned the same way.","items":{"type":"object","required":["name","rate"],"additionalProperties":false,"properties":{"name":{"type":"string"},"rate":{"type":"number","minimum":0,"maximum":100}}}},"taxInclusive":{"type":"boolean"},"discountType":{"type":"string","enum":["percentage","fixed"]},"discountValue":{"type":"number","minimum":0,"description":"A percent from 0 to 100, or a fixed amount in major currency units, by discountType."},"currency":{"type":"string","pattern":"^[A-Z]{3}$"},"dueDate":{"type":"integer","description":"Unix milliseconds."},"terms":{"type":"string"},"notes":{"type":"string"},"dealId":{"type":["string","null"]},"lateFeeEnabled":{"type":"boolean"},"lateFeePercent":{"type":"number"},"paymentInstructions":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "invoices:delete"
      x-seedly-standard-scope: "invoices:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteInvoice
      tags: [Invoices]
      summary: "Delete a draft invoice"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Only drafts can be deleted; void an issued invoice instead."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoices/{id}/void:
    post:
      x-seedly-oauth-scope: "invoices:void"
      x-seedly-standard-scope: "invoices:void"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: voidInvoice
      tags: [Invoices]
      summary: "Void an unpaid invoice"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Requires dedicated invoices:void and exact invoices:send approval before committing. Only unpaid one-time invoices with a customer email can be voided by an app; paid or partly paid invoices and recurring masters or cycles stay staff-only. Any live payment link is expired. The customer cancellation notice is queued at commit and is not cancelled by later app revocation. Refused for test credentials."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoices/{id}/reset-to-draft:
    post:
      x-seedly-oauth-scope: "invoices:write"
      x-seedly-standard-scope: "invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: resetInvoiceToDraft
      tags: [Invoices]
      summary: "Reset an unviewed, unpaid invoice to draft"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoices/{id}/mark-overdue:
    post:
      x-seedly-oauth-scope: "invoices:send"
      x-seedly-standard-scope: "invoices:send"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: markInvoiceOverdue
      tags: [Invoices]
      summary: "Mark an invoice overdue"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Requires invoices:send because an overdue invoice enters the native reminder cadence."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoices/{id}/duplicate:
    post:
      x-seedly-oauth-scope: "invoices:write"
      x-seedly-standard-scope: "invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: duplicateInvoice
      tags: [Invoices]
      summary: "Duplicate an invoice as a draft"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoices/{id}/folder:
    put:
      x-seedly-oauth-scope: "invoices:write"
      x-seedly-standard-scope: "invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: moveInvoice
      tags: [Invoices]
      summary: "Move an invoice to a folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["folderId"],"properties":{"folderId":{"type":["string","null"]}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoices/{id}/deposit:
    post:
      x-seedly-oauth-scope: "invoices:write"
      x-seedly-standard-scope: "invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createInvoiceDeposit
      tags: [Invoices]
      summary: "Create a deposit invoice"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. All invoice money fields are major currency units, for example 19.99, exactly as stored. Totals are computed by the CRM from the line items; a client never supplies them."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["depositPercentage"],"properties":{"depositPercentage":{"type":"number","minimum":0,"maximum":100}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoices/{id}/milestones:
    post:
      x-seedly-oauth-scope: "invoices:write"
      x-seedly-standard-scope: "invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createInvoiceMilestones
      tags: [Invoices]
      summary: "Create milestone invoices"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. All invoice money fields are major currency units, for example 19.99, exactly as stored. Totals are computed by the CRM from the line items; a client never supplies them."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["milestones"],"properties":{"milestones":{"type":"array","maxItems":20,"items":{"type":"object"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoices/{id}/late-fee:
    post:
      x-seedly-oauth-scope: "invoices:send"
      x-seedly-standard-scope: "invoices:send"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: applyInvoiceLateFee
      tags: [Invoices]
      summary: "Apply a late fee"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Requires invoices:send because it raises what the customer is reminded to pay. feePercent is a percent from 0 to 100, for example 1.5; feeAmount is in major currency units."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"feePercent":{"type":"number"},"feeAmount":{"type":"number"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoices/{id}/send:
    post:
      x-seedly-oauth-scope: "invoices:send"
      x-seedly-standard-scope: "invoices:send"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: sendInvoice
      tags: [Invoices]
      summary: "Send an invoice to its customer"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Requires the separate invoices:send authority and enqueues native delivery, which is billable for SMS. A receipt confirms queuing, not delivery. Delivery is rechecked against this credential when it runs; if refused, the invoice reads send_failed and a replay returns suppressed: true. A retry with the same key never sends again. An invoice with a saved recurring schedule also requires exact recurring-invoices:write approval because the send starts billing."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"channel":{"type":"string","enum":["email","sms","both"]}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoices/{id}/delivery:
    get:
      x-seedly-oauth-scope: "invoices:send"
      x-seedly-standard-scope: "invoices:send"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getInvoiceDelivery
      tags: [Invoices]
      summary: "Read delivery status"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. The public customer link is never returned, because it can accept and pay."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoices/{id}/pdf:
    get:
      x-seedly-oauth-scope: "invoices:read"
      x-seedly-standard-scope: "invoices:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getInvoicePdf
      tags: [Invoices]
      summary: "Render the invoice PDF"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Renders through the native generator for this response only and returns the bytes. No storage URL is issued and nothing is stored on the invoice. Customer payment links are always omitted from integration renders. Uses a stricter rendering rate limit."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Authenticated binary content; no storage URL is issued."
          content: {"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoices/{id}/reminders:
    get:
      x-seedly-oauth-scope: "invoices:read"
      x-seedly-standard-scope: "invoices:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listInvoiceReminders
      tags: [Invoices]
      summary: "List reminders sent for an invoice"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoices/{id}/payments:
    get:
      x-seedly-oauth-scope: "payments:read"
      x-seedly-standard-scope: "payments:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listInvoicePayments
      tags: [Payments]
      summary: "List payments on an invoice"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor. amount is in major currency units and may be negative for a refund. Provider identifiers are never returned."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "payments:record"
      x-seedly-standard-scope: "payments:record"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: recordInvoicePayment
      tags: [Payments]
      summary: "Record an offline payment"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Records money received outside the provider. Native paid status, overpayment and workflow behavior applies."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["amount","method"],"properties":{"amount":{"type":"number","minimum":0.01,"description":"Major currency units."},"method":{"type":"string","enum":["cash","check","wire","other"],"description":"Provider payments are recorded only by the provider webhook."},"reference":{"type":"string"},"notes":{"type":"string"},"paidAt":{"type":"integer","description":"Unix milliseconds."}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoices/{id}/installment-payments:
    post:
      x-seedly-oauth-scope: "payments:record"
      x-seedly-standard-scope: "payments:record"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: recordInstallmentPayment
      tags: [Payments]
      summary: "Record an offline installment payment"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["amount","method","installmentId"],"properties":{"amount":{"type":"number","minimum":0.01,"description":"Major currency units."},"method":{"type":"string","enum":["cash","check","wire","other"],"description":"Provider payments are recorded only by the provider webhook."},"reference":{"type":"string"},"notes":{"type":"string"},"paidAt":{"type":"integer","description":"Unix milliseconds."},"installmentId":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoices/{id}/mark-paid:
    post:
      x-seedly-oauth-scope: "payments:record"
      x-seedly-standard-scope: "payments:record"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: markInvoicePaid
      tags: [Payments]
      summary: "Mark an invoice paid"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Marks the whole grand total paid. paidAmount is in major currency units and, when supplied, must equal the grand total; record a partial payment as a payment instead."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"paidAmount":{"type":"number"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoices/{id}/payment-link:
    post:
      x-seedly-oauth-scope: "payments:charge"
      x-seedly-standard-scope: "payments:charge"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: requestInvoicePaymentLink
      tags: [Payments]
      summary: "Request a customer payment link"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Requires the separate payments:charge authority. Queues one provider session under the original credential, which is rechecked before the provider is called. A request while one is in flight queues nothing. The URL is never returned to the integration. Use the approved invoice redelivery route to send the customer their link through the CRM. A customer must still choose to pay; no charge is made."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/payments:
    get:
      x-seedly-oauth-scope: "payments:read"
      x-seedly-standard-scope: "payments:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listPaymentLedger
      tags: [Payments]
      summary: "List the payment ledger"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor. source selects one ledger, invoice by default or external. Each row states amountUnit: invoice rows are major units and external rows are minor units, exactly as stored. from and to are Unix milliseconds. Wallet entries are account billing and are not included."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}},{"name":"source","in":"query","schema":{"type":"string"}},{"name":"from","in":"query","schema":{"type":"string"}},{"name":"to","in":"query","schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoice-folders:
    get:
      x-seedly-oauth-scope: "invoices:read"
      x-seedly-standard-scope: "invoices:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listInvoiceFolders
      tags: [Invoices]
      summary: "List invoice folders"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "invoices:write"
      x-seedly-standard-scope: "invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createInvoiceFolder
      tags: [Invoices]
      summary: "Create an invoice folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"},"parentId":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoice-folders/{id}:
    patch:
      x-seedly-oauth-scope: "invoices:write"
      x-seedly-standard-scope: "invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateInvoiceFolder
      tags: [Invoices]
      summary: "Rename an invoice folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "invoices:delete"
      x-seedly-standard-scope: "invoices:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteInvoiceFolder
      tags: [Invoices]
      summary: "Delete an invoice folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Invoices move to the root. A large folder drains in the background and the response reports draining."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoice-reminder-settings:
    get:
      x-seedly-oauth-scope: "invoices:read"
      x-seedly-standard-scope: "invoices:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getInvoiceReminderSettings
      tags: [Invoices]
      summary: "Read reminder settings"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling."
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    put:
      x-seedly-oauth-scope: "invoices:send"
      x-seedly-standard-scope: "invoices:send"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateInvoiceReminderSettings
      tags: [Invoices]
      summary: "Replace reminder settings"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Requires invoices:send because the native overdue job later delivers these to customers."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["reminders"],"properties":{"reminders":{"type":"array","maxItems":20,"items":{"type":"object"}},"stopOnPayment":{"type":"boolean"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoice-reminder-templates:
    get:
      x-seedly-oauth-scope: "invoices:read"
      x-seedly-standard-scope: "invoices:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listInvoiceReminderTemplates
      tags: [Invoices]
      summary: "List reminder templates"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    put:
      x-seedly-oauth-scope: "invoices:send"
      x-seedly-standard-scope: "invoices:send"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: upsertInvoiceReminderTemplate
      tags: [Invoices]
      summary: "Create or replace a reminder template"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Requires invoices:send because the native overdue job mails this content to customers. One template exists per level. bodyHtml is sanitized and refused if active content survives; subject is plain text."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["level","subject","bodyHtml","bodyText"],"properties":{"level":{"type":"string","enum":["friendly","firm","final"]},"subject":{"type":"string"},"bodyHtml":{"type":"string"},"bodyText":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoice-reminder-templates/{id}:
    delete:
      x-seedly-oauth-scope: "invoices:delete"
      x-seedly-standard-scope: "invoices:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteInvoiceReminderTemplate
      tags: [Invoices]
      summary: "Delete a reminder template"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/estimate-records:
    get:
      x-seedly-oauth-scope: "estimate-records:read"
      x-seedly-standard-scope: "estimate-records:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listEstimateRecords
      tags: [Estimates]
      summary: "List estimates"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor. All estimate money fields are major currency units, exactly as stored. Totals are computed by the CRM from the line items; a client never supplies them. Customer tokens, provider identifiers, signature data and canvas content are never returned. This location-wide roster is separate from the verified-customer booking lookup at /api/v1/booking/estimates and its estimates:read approval."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}},{"name":"status","in":"query","schema":{"type":"string"}},{"name":"contactId","in":"query","schema":{"type":"string"}},{"name":"folderId","in":"query","schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "estimate-records:write"
      x-seedly-standard-scope: "estimate-records:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createEstimateRecord
      tags: [Estimates]
      summary: "Create a draft estimate"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. All estimate money fields are major currency units, exactly as stored. Totals are computed by the CRM from the line items; a client never supplies them. Nothing is sent."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["items"],"properties":{"title":{"type":"string","maxLength":255},"items":{"type":"array","maxItems":500,"items":{"type":"object","required":["quantity","unitPrice"],"additionalProperties":false,"properties":{"description":{"type":"string","maxLength":5000},"quantity":{"type":"number","minimum":0},"unitPrice":{"type":"number","description":"Major currency units."},"productId":{"type":"string","description":"Requires exact products:read detail approval."},"taxable":{"type":"boolean"},"taxRate":{"type":"number","minimum":0,"maximum":100}}}},"validUntil":{"type":"integer","description":"Unix milliseconds."},"taxes":{"type":"array","maxItems":20,"description":"Each rate is a percent from 0 to 100, for example 8.25, and is returned the same way.","items":{"type":"object","required":["name","rate"],"additionalProperties":false,"properties":{"name":{"type":"string"},"rate":{"type":"number","minimum":0,"maximum":100}}}},"taxInclusive":{"type":"boolean"},"currency":{"type":"string","pattern":"^[A-Z]{3}$"},"terms":{"type":"string"},"notes":{"type":"string"},"contactId":{"type":"string","description":"Requires exact contacts:read approval."},"folderId":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/estimate-records/{id}/canvas:
    put:
      x-seedly-oauth-scope: "estimate-records:write"
      x-seedly-standard-scope: "estimate-records:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateEstimateCanvas
      tags: [Estimates]
      summary: "Replace an estimate canvas"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Replaces blocks, pages or globalStyles; omitted ones stay. Blocks use the reviewed content shape: heading, text, divider, spacer, table_of_contents, content_table and terms, plus line_items, optional_items, package_group, picker_single, picker_multiple and signature. HTML is sanitized and the result is checked. Images, video and field blocks are not writable. A stored block this API cannot show must be kept by sending {id, keep: true} in its place; a write that drops one returns 409. At most 100 blocks and 128 KiB a list, 20 pages and 256 KiB of pages. Send blocks or pages, not both; a record with pages takes pages. globalStyles takes color, font, margin and typography tokens. customCss is not writable and is kept. Row quantity is a count and unitPrice is major units. pricing_table is refused because it never reaches the estimate total. Items and totals are recomputed the way acceptance resolves them with nothing selected. A write on a sent or viewed estimate needs exact estimates:send, and the estimate returns to draft and must be sent again. A canvas that prices nothing over stored items is refused, as is a kept row with a line discount. Customer selections cannot be written."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"blocks":{"type":"array","maxItems":100,"items":{"type":"object"}},"pages":{"type":"array","maxItems":20,"items":{"type":"object"}},"globalStyles":{"type":"object"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    get:
      x-seedly-oauth-scope: "estimate-records:read"
      x-seedly-standard-scope: "estimate-records:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getEstimateCanvas
      tags: [Estimates]
      summary: "Read an estimate canvas"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Blocks in the reviewed shape are returned. Any other stored block is returned as {id, type, unsupported: true} so it can be kept on write. clientSelections is what the customer chose and is read only."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/estimate-records/{id}:
    get:
      x-seedly-oauth-scope: "estimate-records:read"
      x-seedly-standard-scope: "estimate-records:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getEstimateRecord
      tags: [Estimates]
      summary: "Read an estimate"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. All estimate money fields are major currency units, exactly as stored. Totals are computed by the CRM from the line items; a client never supplies them. Customer tokens, provider identifiers, signature data and canvas content are never returned. Customer selections and signature data are never returned."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "estimate-records:write"
      x-seedly-standard-scope: "estimate-records:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateEstimateRecord
      tags: [Estimates]
      summary: "Update an estimate"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. All estimate money fields are major currency units, exactly as stored. Totals are computed by the CRM from the line items; a client never supplies them."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"title":{"type":"string","maxLength":255},"items":{"type":"array","maxItems":500,"items":{"type":"object","required":["quantity","unitPrice"],"additionalProperties":false,"properties":{"description":{"type":"string","maxLength":5000},"quantity":{"type":"number","minimum":0},"unitPrice":{"type":"number","description":"Major currency units."},"productId":{"type":"string","description":"Requires exact products:read detail approval."},"taxable":{"type":"boolean"},"taxRate":{"type":"number","minimum":0,"maximum":100}}}},"validUntil":{"type":"integer","description":"Unix milliseconds."},"taxes":{"type":"array","maxItems":20,"description":"Each rate is a percent from 0 to 100, for example 8.25, and is returned the same way.","items":{"type":"object","required":["name","rate"],"additionalProperties":false,"properties":{"name":{"type":"string"},"rate":{"type":"number","minimum":0,"maximum":100}}}},"taxInclusive":{"type":"boolean"},"currency":{"type":"string","pattern":"^[A-Z]{3}$"},"terms":{"type":"string"},"notes":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "estimate-records:delete"
      x-seedly-standard-scope: "estimate-records:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteEstimateRecord
      tags: [Estimates]
      summary: "Delete an estimate"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/estimate-records/{id}/duplicate:
    post:
      x-seedly-oauth-scope: "estimate-records:write"
      x-seedly-standard-scope: "estimate-records:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: duplicateEstimateRecord
      tags: [Estimates]
      summary: "Duplicate an estimate"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/estimate-records/{id}/folder:
    put:
      x-seedly-oauth-scope: "estimate-records:write"
      x-seedly-standard-scope: "estimate-records:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: moveEstimateRecord
      tags: [Estimates]
      summary: "Move an estimate to a folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["folderId"],"properties":{"folderId":{"type":["string","null"]}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/estimate-records/{id}/send:
    post:
      x-seedly-oauth-scope: "estimates:send"
      x-seedly-standard-scope: "estimates:send"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: sendEstimateRecord
      tags: [Estimates]
      summary: "Send an estimate to its customer"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Requires the separate estimates:send authority and enqueues native delivery, which is billable for SMS. A receipt confirms queuing, not delivery. Delivery is rechecked against this credential; if refused the estimate returns to draft and a replay returns suppressed: true. A retry with the same key never sends again."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"channel":{"type":"string","enum":["email","sms","both"]}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/estimate-records/{id}/delivery:
    get:
      x-seedly-oauth-scope: "estimates:send"
      x-seedly-standard-scope: "estimates:send"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getEstimateDelivery
      tags: [Estimates]
      summary: "Read delivery status"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. The public customer link is never returned, because it can sign."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/estimate-records/{id}/convert:
    post:
      x-seedly-oauth-scope: "estimates:convert"
      x-seedly-standard-scope: "estimates:convert"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: convertEstimateRecord
      tags: [Estimates]
      summary: "Convert an estimate to an invoice"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Requires the separate estimates:convert authority. Only an accepted estimate converts; anything else receives 409. result is the new invoice ID."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/estimate-folders:
    get:
      x-seedly-oauth-scope: "estimate-records:read"
      x-seedly-standard-scope: "estimate-records:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listEstimateFolders
      tags: [Estimates]
      summary: "List estimate folders"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "estimate-records:write"
      x-seedly-standard-scope: "estimate-records:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createEstimateFolder
      tags: [Estimates]
      summary: "Create an estimate folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"},"parentId":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/estimate-folders/{id}:
    patch:
      x-seedly-oauth-scope: "estimate-records:write"
      x-seedly-standard-scope: "estimate-records:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateEstimateFolder
      tags: [Estimates]
      summary: "Rename an estimate folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "estimate-records:delete"
      x-seedly-standard-scope: "estimate-records:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteEstimateFolder
      tags: [Estimates]
      summary: "Delete an estimate folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/recurring-invoices:
    get:
      x-seedly-oauth-scope: "recurring-invoices:read"
      x-seedly-standard-scope: "recurring-invoices:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listRecurringInvoices
      tags: [Recurring Invoices]
      summary: "List recurring invoice schedules"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor. All money fields are major currency units, exactly as stored. Totals are computed by the CRM. These are schedules this location bills its customers, not the CRM account subscription, which is account billing."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}},{"name":"status","in":"query","schema":{"type":"string"}},{"name":"folderId","in":"query","schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "recurring-invoices:write"
      x-seedly-standard-scope: "recurring-invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createRecurringInvoice
      tags: [Recurring Invoices]
      summary: "Create a recurring invoice schedule"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. All money fields are major currency units, exactly as stored. Totals are computed by the CRM. These are schedules this location bills its customers, not the CRM account subscription, which is account billing. Once active the native engine generates invoices on the cadence and, with autoSend, delivers them. autoSend true needs exact invoices:send approval. A nextInvoiceDate now or in the past needs exact recurring-invoices:execute approval, and the next engine run bills it. The engine rechecks this credential before each generation and pauses the schedule when that authority has ended. Refused for test credentials when the schedule auto-sends."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name","items","frequency","nextInvoiceDate"],"properties":{"contactId":{"type":"string","description":"Requires exact contacts:read approval."},"name":{"type":"string","maxLength":255},"items":{"type":"array","maxItems":500,"items":{"type":"object","required":["quantity","unitPrice"],"additionalProperties":false,"properties":{"description":{"type":"string","maxLength":5000},"quantity":{"type":"number","minimum":0},"unitPrice":{"type":"number","description":"Major currency units."},"productId":{"type":"string","description":"Requires exact products:read detail approval."},"taxable":{"type":"boolean"},"taxRate":{"type":"number","minimum":0,"maximum":100}}}},"frequency":{"type":"string","enum":["weekly","biweekly","monthly","quarterly","yearly"]},"nextInvoiceDate":{"type":"integer","description":"Unix milliseconds."},"autoSend":{"type":"boolean"},"lateFeeEnabled":{"type":"boolean"},"lateFeePercent":{"type":"number","description":"Percent, for example 1.5."},"taxes":{"type":"array","maxItems":20,"description":"Each rate is a percent from 0 to 100, for example 8.25, and is returned the same way.","items":{"type":"object","required":["name","rate"],"additionalProperties":false,"properties":{"name":{"type":"string"},"rate":{"type":"number","minimum":0,"maximum":100}}}},"taxInclusive":{"type":"boolean"},"discountType":{"type":"string","enum":["percentage","fixed"]},"discountValue":{"type":"number","minimum":0,"description":"A percent from 0 to 100, or a fixed amount in major currency units, by discountType."},"currency":{"type":"string","pattern":"^[A-Z]{3}$"},"terms":{"type":"string"},"notes":{"type":"string"},"folderId":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/recurring-invoices/{id}:
    get:
      x-seedly-oauth-scope: "recurring-invoices:read"
      x-seedly-standard-scope: "recurring-invoices:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getRecurringInvoice
      tags: [Recurring Invoices]
      summary: "Read a recurring invoice schedule"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. All money fields are major currency units, exactly as stored. Totals are computed by the CRM. These are schedules this location bills its customers, not the CRM account subscription, which is account billing."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "recurring-invoices:write"
      x-seedly-standard-scope: "recurring-invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateRecurringInvoice
      tags: [Recurring Invoices]
      summary: "Update a recurring invoice schedule"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. All money fields are major currency units, exactly as stored. Totals are computed by the CRM. These are schedules this location bills its customers, not the CRM account subscription, which is account billing. The same autoSend and due-date approvals as create apply. On a schedule that auto-sends, any change except a rename or turning autoSend off needs exact invoices:send approval, because the schedule mails what it describes, and the schedule then answers to this credential. Refused for test credentials when the schedule auto-sends."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"contactId":{"type":"string","description":"Requires exact contacts:read approval."},"name":{"type":"string","maxLength":255},"items":{"type":"array","maxItems":500,"items":{"type":"object","required":["quantity","unitPrice"],"additionalProperties":false,"properties":{"description":{"type":"string","maxLength":5000},"quantity":{"type":"number","minimum":0},"unitPrice":{"type":"number","description":"Major currency units."},"productId":{"type":"string","description":"Requires exact products:read detail approval."},"taxable":{"type":"boolean"},"taxRate":{"type":"number","minimum":0,"maximum":100}}}},"frequency":{"type":"string","enum":["weekly","biweekly","monthly","quarterly","yearly"]},"nextInvoiceDate":{"type":"integer","description":"Unix milliseconds."},"autoSend":{"type":"boolean"},"lateFeeEnabled":{"type":"boolean"},"lateFeePercent":{"type":"number","description":"Percent, for example 1.5."},"taxes":{"type":"array","maxItems":20,"description":"Each rate is a percent from 0 to 100, for example 8.25, and is returned the same way.","items":{"type":"object","required":["name","rate"],"additionalProperties":false,"properties":{"name":{"type":"string"},"rate":{"type":"number","minimum":0,"maximum":100}}}},"taxInclusive":{"type":"boolean"},"discountType":{"type":"string","enum":["percentage","fixed"]},"discountValue":{"type":"number","minimum":0,"description":"A percent from 0 to 100, or a fixed amount in major currency units, by discountType."},"currency":{"type":"string","pattern":"^[A-Z]{3}$"},"terms":{"type":"string"},"notes":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/recurring-invoices/{id}/invoices:
    get:
      x-seedly-oauth-scope: "recurring-invoices:read"
      x-seedly-standard-scope: "recurring-invoices:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listRecurringGeneratedInvoices
      tags: [Recurring Invoices]
      summary: "List invoices generated by a schedule"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor. All money fields are major currency units, exactly as stored. Totals are computed by the CRM. These are schedules this location bills its customers, not the CRM account subscription, which is account billing."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/recurring-invoices/{id}/pause:
    post:
      x-seedly-oauth-scope: "recurring-invoices:write"
      x-seedly-standard-scope: "recurring-invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: pauseRecurringInvoice
      tags: [Recurring Invoices]
      summary: "Pause a schedule"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/recurring-invoices/{id}/resume:
    post:
      x-seedly-oauth-scope: "recurring-invoices:write"
      x-seedly-standard-scope: "recurring-invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: resumeRecurringInvoice
      tags: [Recurring Invoices]
      summary: "Resume a schedule"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. autoSend schedules need exact invoices:send approval and an overdue schedule needs exact recurring-invoices:execute approval. The schedule then answers to this credential. Refused for test credentials when the schedule auto-sends."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/recurring-invoices/{id}/cancel:
    post:
      x-seedly-oauth-scope: "recurring-invoices:write"
      x-seedly-standard-scope: "recurring-invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: cancelRecurringInvoice
      tags: [Recurring Invoices]
      summary: "Cancel a schedule"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/recurring-invoices/{id}/skip-next:
    post:
      x-seedly-oauth-scope: "recurring-invoices:write"
      x-seedly-standard-scope: "recurring-invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: skipRecurringInvoice
      tags: [Recurring Invoices]
      summary: "Skip the next generation"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/recurring-invoices/{id}/duplicate:
    post:
      x-seedly-oauth-scope: "recurring-invoices:write"
      x-seedly-standard-scope: "recurring-invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: duplicateRecurringInvoice
      tags: [Recurring Invoices]
      summary: "Duplicate a schedule"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. The copy starts paused."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/recurring-invoices/{id}/rate-change:
    post:
      x-seedly-oauth-scope: "recurring-invoices:write"
      x-seedly-standard-scope: "recurring-invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: scheduleRecurringRateChange
      tags: [Recurring Invoices]
      summary: "Schedule a rate change"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. All money fields are major currency units, exactly as stored. Totals are computed by the CRM. These are schedules this location bills its customers, not the CRM account subscription, which is account billing. An auto-send schedule needs exact invoices:send approval. Refused for test credentials when the schedule auto-sends."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["items","effectiveDate"],"properties":{"items":{"type":"array","maxItems":500,"items":{"type":"object","required":["quantity","unitPrice"],"additionalProperties":false,"properties":{"description":{"type":"string","maxLength":5000},"quantity":{"type":"number","minimum":0},"unitPrice":{"type":"number","description":"Major currency units."},"productId":{"type":"string","description":"Requires exact products:read detail approval."},"taxable":{"type":"boolean"},"taxRate":{"type":"number","minimum":0,"maximum":100}}}},"effectiveDate":{"type":"integer","description":"Unix milliseconds."},"taxes":{"type":"array","maxItems":20,"description":"Each rate is a percent from 0 to 100, for example 8.25, and is returned the same way.","items":{"type":"object","required":["name","rate"],"additionalProperties":false,"properties":{"name":{"type":"string"},"rate":{"type":"number","minimum":0,"maximum":100}}}},"taxInclusive":{"type":"boolean"},"discountType":{"type":"string","enum":["percentage","fixed"]},"discountValue":{"type":"number","minimum":0,"description":"A percent from 0 to 100, or a fixed amount in major currency units, by discountType."}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/recurring-invoices/{id}/cancel-rate-change:
    post:
      x-seedly-oauth-scope: "recurring-invoices:write"
      x-seedly-standard-scope: "recurring-invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: cancelRecurringRateChange
      tags: [Recurring Invoices]
      summary: "Cancel a scheduled rate change"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. An auto-send schedule needs exact invoices:send approval. Refused for test credentials when the schedule auto-sends."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/recurring-invoices/{id}/generate:
    post:
      x-seedly-oauth-scope: "recurring-invoices:execute"
      x-seedly-standard-scope: "recurring-invoices:execute"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: generateRecurringInvoiceNow
      tags: [Recurring Invoices]
      summary: "Generate the next invoice now"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Requires the separate recurring-invoices:execute authority. Creates a real invoice and, with autoSend, delivers it to the customer. A retry with the same key never generates again. An autoSend schedule also needs exact invoices:send approval. Refused for test credentials when the schedule auto-sends."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/recurring-invoices/{id}/folder:
    put:
      x-seedly-oauth-scope: "recurring-invoices:write"
      x-seedly-standard-scope: "recurring-invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: moveRecurringInvoice
      tags: [Recurring Invoices]
      summary: "Move a schedule to a folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["folderId"],"properties":{"folderId":{"type":["string","null"]}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/recurring-invoice-folders:
    get:
      x-seedly-oauth-scope: "recurring-invoices:read"
      x-seedly-standard-scope: "recurring-invoices:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listRecurringInvoiceFolders
      tags: [Recurring Invoices]
      summary: "List schedule folders"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "recurring-invoices:write"
      x-seedly-standard-scope: "recurring-invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createRecurringInvoiceFolder
      tags: [Recurring Invoices]
      summary: "Create a schedule folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"},"parentId":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/recurring-invoice-folders/{id}:
    patch:
      x-seedly-oauth-scope: "recurring-invoices:write"
      x-seedly-standard-scope: "recurring-invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateRecurringInvoiceFolder
      tags: [Recurring Invoices]
      summary: "Rename a schedule folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "recurring-invoices:write"
      x-seedly-standard-scope: "recurring-invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteRecurringInvoiceFolder
      tags: [Recurring Invoices]
      summary: "Delete a schedule folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/invoices/{id}/recurring-settings:
    put:
      x-seedly-oauth-scope: "recurring-invoices:write"
      x-seedly-standard-scope: "recurring-invoices:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateInvoiceRecurringSettings
      tags: [Recurring Invoices]
      summary: "Replace an invoice recurring settings"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Saved settings on a draft start a schedule when the invoice is sent. On a recurring master they change future cycles. autoSend true needs exact invoices:send approval and a startDate now or in the past needs exact recurring-invoices:execute approval. Refused for test credentials when the schedule auto-sends."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["enabled","frequency"],"properties":{"enabled":{"type":"boolean"},"frequency":{"type":"string","enum":["weekly","biweekly","monthly","quarterly","yearly"]},"startDate":{"type":"integer"},"autoSend":{"type":"boolean"},"endAfterCount":{"type":"integer"},"endDate":{"type":"integer"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/documents:
    get:
      x-seedly-oauth-scope: "documents:read"
      x-seedly-standard-scope: "documents:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listDocuments
      tags: [Documents]
      summary: "List documents"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor. Signing stays with the recipient: no operation accepts a signature, a signed status, a consent flag or a recipient token, and none returns a public access token, signature image or signer token."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}},{"name":"status","in":"query","schema":{"type":"string"}},{"name":"contactId","in":"query","schema":{"type":"string"}},{"name":"folderId","in":"query","schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "documents:write"
      x-seedly-standard-scope: "documents:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createDocument
      tags: [Documents]
      summary: "Create a draft document"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Signing stays with the recipient: no operation accepts a signature, a signed status, a consent flag or a recipient token, and none returns a public access token, signature image or signer token. A template or plain HTML content can seed it. Canvas blocks, fillable fields and payment or auto-invoice settings are not available through this contract. Nothing is sent."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["title"],"properties":{"contactId":{"type":"string","description":"Requires exact contacts:read approval."},"title":{"type":"string","maxLength":500},"content":{"type":"string","description":"HTML, sanitized with the strict profile on write."},"signatureRequired":{"type":"boolean"},"expiresAt":{"type":"integer","description":"Unix milliseconds."},"recipients":{"type":"array","maxItems":50,"items":{"type":"object","required":["email"],"additionalProperties":false,"properties":{"contactId":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"},"role":{"type":"string","enum":["signer","viewer"]},"signOrder":{"type":"integer"}}}},"ccRecipients":{"type":"array","maxItems":50,"items":{"type":"object"}},"signingMode":{"type":"string","enum":["sequential","parallel"]},"templateId":{"type":"string"},"folderId":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/documents/{id}/canvas:
    put:
      x-seedly-oauth-scope: "documents:write"
      x-seedly-standard-scope: "documents:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateDocumentCanvas
      tags: [Documents]
      summary: "Replace a document canvas"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Replaces blocks, pages or globalStyles; omitted ones stay. Blocks use the reviewed content shape: heading, text, divider, spacer, table_of_contents, content_table and terms, plus pricing_table and signature. HTML is sanitized and the result is checked. Images, video and field blocks are not writable. A stored block this API cannot show must be kept by sending {id, keep: true} in its place; a write that drops one returns 409. At most 100 blocks and 128 KiB a list, 20 pages and 256 KiB of pages. Send blocks or pages, not both; a record with pages takes pages. globalStyles takes color, font, margin and typography tokens. customCss is not writable and is kept. Draft documents only. Document content and product rows are regenerated from the blocks; pages also replace blocks. At most one pricing_table, with taxRate as a percent and no discount or tax list. Its rows and tax are the billing source: removing it clears them, and changing them under a stored auto-invoice needs the exact invoice create approval. A signature block carries a label and no value. The API cannot sign."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"blocks":{"type":"array","maxItems":100,"items":{"type":"object"}},"pages":{"type":"array","maxItems":20,"items":{"type":"object"}},"globalStyles":{"type":"object"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    get:
      x-seedly-oauth-scope: "documents:read"
      x-seedly-standard-scope: "documents:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getDocumentCanvas
      tags: [Documents]
      summary: "Read a document canvas"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Blocks in the reviewed shape are returned. Any other stored block is returned as {id, type, unsupported: true} so it can be kept on write. fillableFields is layout only: a value a signer entered is never returned. Product amounts are major units and productTaxRate is a percent such as 8.25."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/documents/{id}:
    get:
      x-seedly-oauth-scope: "documents:read"
      x-seedly-standard-scope: "documents:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getDocument
      tags: [Documents]
      summary: "Read a document"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Signing stays with the recipient: no operation accepts a signature, a signed status, a consent flag or a recipient token, and none returns a public access token, signature image or signer token. Recipient and cc names and emails need exact contacts:read approval; without it only signing state is returned. A recipient whose contact was deleted is left out."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "documents:write"
      x-seedly-standard-scope: "documents:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateDocument
      tags: [Documents]
      summary: "Update a document"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Signing stays with the recipient: no operation accepts a signature, a signed status, a consent flag or a recipient token, and none returns a public access token, signature image or signer token. Native status rules apply."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"contactId":{"type":"string","description":"Requires exact contacts:read approval."},"title":{"type":"string","maxLength":500},"content":{"type":"string","description":"HTML, sanitized with the strict profile on write."},"signatureRequired":{"type":"boolean"},"expiresAt":{"type":"integer","description":"Unix milliseconds."},"recipients":{"type":"array","maxItems":50,"items":{"type":"object","required":["email"],"additionalProperties":false,"properties":{"contactId":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"},"role":{"type":"string","enum":["signer","viewer"]},"signOrder":{"type":"integer"}}}},"ccRecipients":{"type":"array","maxItems":50,"items":{"type":"object"}},"signingMode":{"type":"string","enum":["sequential","parallel"]}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "documents:delete"
      x-seedly-standard-scope: "documents:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteDocument
      tags: [Documents]
      summary: "Delete a document"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Native rules apply, including protection of signed documents."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/documents/{id}/brand-style:
    post:
      x-seedly-oauth-scope: "documents:write"
      x-seedly-standard-scope: "documents:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: applyDocumentBrandStyle
      tags: [Documents]
      summary: "Apply a brand style to a document"
      description: "Replaces the document's stored styles with the tokens of a brand style in this location. Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval, and the GET brand style operation under brand-styles:read is required as well. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority, return the original receipt and never reapply the change. Unknown fields are rejected. Only a draft document can be restyled, as with the canvas route. Any other status, or a recorded signature, returns 409. A brand style native validation refuses returns 409."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["brandStyleId"],"properties":{"brandStyleId":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/documents/{id}/duplicate:
    post:
      x-seedly-oauth-scope: "documents:write"
      x-seedly-standard-scope: "documents:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: duplicateDocument
      tags: [Documents]
      summary: "Duplicate a document"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. The copy starts as an unsigned draft."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/documents/{id}/folder:
    put:
      x-seedly-oauth-scope: "documents:write"
      x-seedly-standard-scope: "documents:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: moveDocument
      tags: [Documents]
      summary: "Move a document to a folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["folderId"],"properties":{"folderId":{"type":["string","null"]}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/documents/{id}/send:
    post:
      x-seedly-oauth-scope: "documents:send"
      x-seedly-standard-scope: "documents:send"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: sendDocument
      tags: [Documents]
      summary: "Send a document to its recipients"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Signing stays with the recipient: no operation accepts a signature, a signed status, a consent flag or a recipient token, and none returns a public access token, signature image or signer token. Requires the separate documents:send authority and enqueues native delivery, which is billable for SMS. A receipt confirms queuing, not delivery. Delivery is rechecked against this credential; if refused the document returns to draft and a replay returns suppressed: true. A retry with the same key never sends again."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"channel":{"type":"string","enum":["email","sms","both"]}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/documents/{id}/reminders:
    post:
      x-seedly-oauth-scope: "documents:send"
      x-seedly-standard-scope: "documents:send"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: sendDocumentReminder
      tags: [Documents]
      summary: "Send a reminder to pending recipients"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Requires the separate documents:send authority. A retry with the same key never sends again."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/documents/{id}/delivery:
    get:
      x-seedly-oauth-scope: "documents:send"
      x-seedly-standard-scope: "documents:send"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getDocumentDelivery
      tags: [Documents]
      summary: "Read delivery status"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Signing stays with the recipient: no operation accepts a signature, a signed status, a consent flag or a recipient token, and none returns a public access token, signature image or signer token. Recipient and cc names and emails need exact contacts:read approval; without it only signing state is returned."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/documents/{id}/certificate:
    get:
      x-seedly-oauth-scope: "documents:read"
      x-seedly-standard-scope: "documents:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getDocumentCertificate
      tags: [Documents]
      summary: "Read the signing audit certificate"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Available once signed. Contains signer names, emails, IP addresses and consent evidence, and the fixed audit trail. Raw event metadata is not returned. Reads the newest 2,000 related activity rows; auditTrailTruncated is true when older rows were not read, so treat the trail and consent evidence as partial."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/documents/{id}/pdf:
    get:
      x-seedly-oauth-scope: "documents:read"
      x-seedly-standard-scope: "documents:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getDocumentPdf
      tags: [Documents]
      summary: "Render the document PDF"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. A signed document returns the PDF stored after signing, unchanged. Anything else is rendered for this response only and never stored. Bytes are returned on this authenticated response and no storage URL is issued. Unavailable in a HIPAA location. Uses a stricter rendering rate limit."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Authenticated binary content; no storage URL is issued."
          content: {"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/documents/{id}/versions:
    get:
      x-seedly-oauth-scope: "documents:read"
      x-seedly-standard-scope: "documents:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listDocumentVersions
      tags: [Documents]
      summary: "List document versions"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/document-versions/{id}:
    get:
      x-seedly-oauth-scope: "documents:read"
      x-seedly-standard-scope: "documents:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getDocumentVersion
      tags: [Documents]
      summary: "Read a document version"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/document-versions/{id}/restore:
    post:
      x-seedly-oauth-scope: "documents:write"
      x-seedly-standard-scope: "documents:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: restoreDocumentVersion
      tags: [Documents]
      summary: "Restore a document version"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/document-reminder-settings:
    get:
      x-seedly-oauth-scope: "documents:read"
      x-seedly-standard-scope: "documents:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getDocumentReminderSettings
      tags: [Documents]
      summary: "Read document reminder settings"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling."
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    put:
      x-seedly-oauth-scope: "documents:send"
      x-seedly-standard-scope: "documents:send"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateDocumentReminderSettings
      tags: [Documents]
      summary: "Replace document reminder settings"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Requires documents:send because the native job later delivers these to recipients."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["reminders"],"properties":{"reminders":{"type":"array","maxItems":20,"items":{"type":"object"}},"stopOnSign":{"type":"boolean"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/document-templates:
    get:
      x-seedly-oauth-scope: "documents:read"
      x-seedly-standard-scope: "documents:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listDocumentTemplates
      tags: [Documents]
      summary: "List document templates"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "documents:write"
      x-seedly-standard-scope: "documents:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createDocumentTemplate
      tags: [Documents]
      summary: "Create a document template"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string","maxLength":255},"content":{"type":"string","description":"HTML, sanitized with the strict profile on write."},"signatureRequired":{"type":"boolean"},"category":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/document-templates/{id}/canvas:
    put:
      x-seedly-oauth-scope: "documents:write"
      x-seedly-standard-scope: "documents:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateDocumentTemplateCanvas
      tags: [Documents]
      summary: "Replace a document template canvas"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. The same block rules as a document canvas. Keep a stored block this API cannot show by sending {id, keep: true}; a write that drops one returns 409."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"blocks":{"type":"array","maxItems":100,"items":{"type":"object"}},"pages":{"type":"array","maxItems":20,"items":{"type":"object"}},"globalStyles":{"type":"object"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    get:
      x-seedly-oauth-scope: "documents:read"
      x-seedly-standard-scope: "documents:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getDocumentTemplateCanvas
      tags: [Documents]
      summary: "Read a document template canvas"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Blocks in the reviewed shape are returned. Any other stored block is returned as {id, type, unsupported: true} so it can be kept on write."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/document-templates/{id}:
    get:
      x-seedly-oauth-scope: "documents:read"
      x-seedly-standard-scope: "documents:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getDocumentTemplate
      tags: [Documents]
      summary: "Read a document template"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "documents:write"
      x-seedly-standard-scope: "documents:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateDocumentTemplate
      tags: [Documents]
      summary: "Update a document template"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":255},"content":{"type":"string","description":"HTML, sanitized with the strict profile on write."},"signatureRequired":{"type":"boolean"},"category":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "documents:delete"
      x-seedly-standard-scope: "documents:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteDocumentTemplate
      tags: [Documents]
      summary: "Delete a document template"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/document-templates/{id}/brand-style:
    post:
      x-seedly-oauth-scope: "documents:write"
      x-seedly-standard-scope: "documents:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: applyDocumentTemplateBrandStyle
      tags: [Documents]
      summary: "Apply a brand style to a document template"
      description: "Replaces the template's stored styles with the tokens of a brand style in this location. Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval, and the GET brand style operation under brand-styles:read is required as well. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority, return the original receipt and never reapply the change. Unknown fields are rejected. Documents already created from the template keep their styles. A brand style native validation refuses returns 409."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["brandStyleId"],"properties":{"brandStyleId":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/document-templates/{id}/folder:
    put:
      x-seedly-oauth-scope: "documents:write"
      x-seedly-standard-scope: "documents:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: moveDocumentTemplate
      tags: [Documents]
      summary: "Move a template to a folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["folderId"],"properties":{"folderId":{"type":["string","null"]}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/document-folders:
    get:
      x-seedly-oauth-scope: "documents:read"
      x-seedly-standard-scope: "documents:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listDocumentFolders
      tags: [Documents]
      summary: "List document folders"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "documents:write"
      x-seedly-standard-scope: "documents:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createDocumentFolder
      tags: [Documents]
      summary: "Create a document folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"},"parentId":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/document-folders/{id}:
    patch:
      x-seedly-oauth-scope: "documents:write"
      x-seedly-standard-scope: "documents:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateDocumentFolder
      tags: [Documents]
      summary: "Rename a document folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "documents:delete"
      x-seedly-standard-scope: "documents:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteDocumentFolder
      tags: [Documents]
      summary: "Delete a document folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/document-template-folders:
    get:
      x-seedly-oauth-scope: "documents:read"
      x-seedly-standard-scope: "documents:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listDocumentTemplateFolders
      tags: [Documents]
      summary: "List template folders"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "documents:write"
      x-seedly-standard-scope: "documents:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createDocumentTemplateFolder
      tags: [Documents]
      summary: "Create a template folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"},"parentId":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/document-template-folders/{id}:
    patch:
      x-seedly-oauth-scope: "documents:write"
      x-seedly-standard-scope: "documents:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateDocumentTemplateFolder
      tags: [Documents]
      summary: "Rename a template folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "documents:delete"
      x-seedly-standard-scope: "documents:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteDocumentTemplateFolder
      tags: [Documents]
      summary: "Delete a template folder"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/document-flows:
    get:
      x-seedly-oauth-scope: "documents:read"
      x-seedly-standard-scope: "documents:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: listDocumentFlows
      tags: [Documents]
      summary: "List document flows"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Pages scan at most 50 rows, default 25; filters may leave an empty page, so follow meta.cursor. Signing stays with the recipient: no operation accepts a signature, a signed status, a consent flag or a recipient token, and none returns a public access token, signature image or signer token."
      parameters: [{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":16384}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"$ref":"#/components/schemas/ProfileReadPage"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    post:
      x-seedly-oauth-scope: "documents:write"
      x-seedly-standard-scope: "documents:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createDocumentFlow
      tags: [Documents]
      summary: "Create a document flow"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. At most 50 steps. A document, estimate or invoice step needs exact read approval for that family and a live same-location record. The public flow token is never returned."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name","steps"],"properties":{"name":{"type":"string"},"contactId":{"type":"string"},"steps":{"type":"array","maxItems":50,"items":{"type":"object"}}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/document-flows/{id}:
    get:
      x-seedly-oauth-scope: "documents:read"
      x-seedly-standard-scope: "documents:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getDocumentFlow
      tags: [Documents]
      summary: "Read a document flow"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Signing stays with the recipient: no operation accepts a signature, a signed status, a consent flag or a recipient token, and none returns a public access token, signature image or signer token."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "documents:write"
      x-seedly-standard-scope: "documents:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateDocumentFlow
      tags: [Documents]
      summary: "Update a document flow"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      requestBody:
        required: true
        content: {"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string"},"contactId":{"type":"string"}}}}}
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
    delete:
      x-seedly-oauth-scope: "documents:delete"
      x-seedly-standard-scope: "documents:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: deleteDocumentFlow
      tags: [Documents]
      summary: "Delete a document flow"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/document-flows/{id}/activate:
    post:
      x-seedly-oauth-scope: "documents:send"
      x-seedly-standard-scope: "documents:send"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: activateDocumentFlow
      tags: [Documents]
      summary: "Activate a document flow"
      description: "Location-wide Standard v2 or OAuth only; each exact operation needs explicit approval. Legacy keys and own/team/selected grants are denied. Native location permissions apply and OAuth also revalidates the current user, role and token ceiling. Requires Idempotency-Key. Replays recheck current authority and target state, return the original receipt and never reapply the change. Unknown fields are rejected. Requires the separate documents:send authority because activation opens the flow to its recipient. Steps advance only when the recipient completes them."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}]
      responses:
        '200':
          description: "Success."
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid parameters or payload.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing authority, stale operation approval, or restricted grant.
        '404':
          description: Record unavailable in this location.
        '409':
          description: Conflict with current state or an earlier Idempotency-Key request.
        '429':
          description: Rate limit exceeded.
  /api/v1/content-library/advanced:
    post:
      x-seedly-oauth-scope: "documents:write"
      x-seedly-standard-scope: "documents:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: createAdvancedContentLibrary
      tags: [Content Assets]
      summary: "createAdvancedContentLibrary"
      description: "Explicit advanced-route approval required under the documents bucket; existing common-block Standard approvals do not grant this operation. Location-wide Standard v2 or OAuth only. Legacy keys and own/team/selected-record grants cannot use these operations. Native location permissions apply; OAuth also revalidates the current user. No sending, document signing, workflow execution, or provider calls. Stable Idempotency-Key required. Unknown fields rejected. Replays recheck current authorization and target relationships, return the original receipt, and do not reapply changes. Library blocks support reviewed common content, pricing_table, line_items, optional_items, package_group, picker_single, picker_multiple, terms and signature label definitions, with at most 100 blocks and 128 KiB serialized blocks. Priced rows use major currency units, require name or description, and any amount must equal rounded quantity times unitPrice. Row and subtotal amounts are capped at one billion; combined tax and percentage discount are capped at 100 percent. At most 20 distinct product references are allowed, with a sequential 512-KiB cumulative stored-product proof budget plus one maximum-size record before rejection. Product IDs additionally require current exact products:read detail approval and an active same-location product on detail/create/update/replay, including sparse edits retaining references. Stored prices are explicit negotiated values and are not refreshed from the catalog. Recipient response, signed state and provider fields cannot be supplied. Rich text is sanitized with the strict profile; embedded media is removed. Media, document field bindings, CPQ, per-row tax/discount/recurrence and extension blocks remain unsupported. Signature blocks contain only a label, never signed state or signature URLs. Existing richtext/paragraph/toc aliases are read without renaming; legacy plain text remains plain text. Existing unsupported block families cannot be fetched through this detail contract. "
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentAssetAdvancedLibraryCreate"}}}}
      responses:
        '200':
          description: Authorized data or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input or unsupported content shape.
        '401':
          description: Missing or invalid credential.
        '403':
          description: Missing scope, stale approval, revoked authority or unsupported record grant.
        '404':
          description: Target unavailable in this location.
        '409':
          description: Conflicting idempotency request or folder deletion in progress.
        '429':
          description: Rate limit exceeded.
  /api/v1/content-library/{id}/advanced:
    get:
      x-seedly-oauth-scope: "documents:read"
      x-seedly-standard-scope: "documents:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getAdvancedContentLibrary
      tags: [Content Assets]
      summary: "getAdvancedContentLibrary"
      description: "Explicit advanced-route approval required under the documents bucket; existing common-block Standard approvals do not grant this operation. Location-wide Standard v2 or OAuth only. Legacy keys and own/team/selected-record grants cannot use these operations. Native location permissions apply; OAuth also revalidates the current user. No sending, document signing, workflow execution, or provider calls. Library blocks support reviewed common content, pricing_table, line_items, optional_items, package_group, picker_single, picker_multiple, terms and signature label definitions, with at most 100 blocks and 128 KiB serialized blocks. Priced rows use major currency units, require name or description, and any amount must equal rounded quantity times unitPrice. Row and subtotal amounts are capped at one billion; combined tax and percentage discount are capped at 100 percent. At most 20 distinct product references are allowed, with a sequential 512-KiB cumulative stored-product proof budget plus one maximum-size record before rejection. Product IDs additionally require current exact products:read detail approval and an active same-location product on detail/create/update/replay, including sparse edits retaining references. Stored prices are explicit negotiated values and are not refreshed from the catalog. Recipient response, signed state and provider fields cannot be supplied. Rich text is sanitized with the strict profile; embedded media is removed. Media, document field bindings, CPQ, per-row tax/discount/recurrence and extension blocks remain unsupported. Signature blocks contain only a label, never signed state or signature URLs. Existing richtext/paragraph/toc aliases are read without renaming; legacy plain text remains plain text. Existing unsupported block families cannot be fetched through this detail contract. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized data or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input or unsupported content shape.
        '401':
          description: Missing or invalid credential.
        '403':
          description: Missing scope, stale approval, revoked authority or unsupported record grant.
        '404':
          description: Target unavailable in this location.
        '409':
          description: Conflicting idempotency request or folder deletion in progress.
        '429':
          description: Rate limit exceeded.
    patch:
      x-seedly-oauth-scope: "documents:write"
      x-seedly-standard-scope: "documents:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: updateAdvancedContentLibrary
      tags: [Content Assets]
      summary: "updateAdvancedContentLibrary"
      description: "Explicit advanced-route approval required under the documents bucket; existing common-block Standard approvals do not grant this operation. Location-wide Standard v2 or OAuth only. Legacy keys and own/team/selected-record grants cannot use these operations. Native location permissions apply; OAuth also revalidates the current user. No sending, document signing, workflow execution, or provider calls. Stable Idempotency-Key required. Unknown fields rejected. Replays recheck current authorization and target relationships, return the original receipt, and do not reapply changes. Library blocks support reviewed common content, pricing_table, line_items, optional_items, package_group, picker_single, picker_multiple, terms and signature label definitions, with at most 100 blocks and 128 KiB serialized blocks. Priced rows use major currency units, require name or description, and any amount must equal rounded quantity times unitPrice. Row and subtotal amounts are capped at one billion; combined tax and percentage discount are capped at 100 percent. At most 20 distinct product references are allowed, with a sequential 512-KiB cumulative stored-product proof budget plus one maximum-size record before rejection. Product IDs additionally require current exact products:read detail approval and an active same-location product on detail/create/update/replay, including sparse edits retaining references. Stored prices are explicit negotiated values and are not refreshed from the catalog. Recipient response, signed state and provider fields cannot be supplied. Rich text is sanitized with the strict profile; embedded media is removed. Media, document field bindings, CPQ, per-row tax/discount/recurrence and extension blocks remain unsupported. Signature blocks contain only a label, never signed state or signature URLs. Existing richtext/paragraph/toc aliases are read without renaming; legacy plain text remains plain text. Existing unsupported block families cannot be fetched through this detail contract. "
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentAssetAdvancedLibraryUpdate"}}}}
      responses:
        '200':
          description: Authorized data or durable receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object"}}}}}
        '400':
          description: Invalid input or unsupported content shape.
        '401':
          description: Missing or invalid credential.
        '403':
          description: Missing scope, stale approval, revoked authority or unsupported record grant.
        '404':
          description: Target unavailable in this location.
        '409':
          description: Conflicting idempotency request or folder deletion in progress.
        '429':
          description: Rate limit exceeded.
  /api/v1/task-tags:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "List task tag definitions"
      description: "Pages catalog definitions, not contact tags. Tag names can also exist on tasks without a definition; read those from the task. Location-wide Standard v2 or OAuth operation. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Create a task tag definition"
      description: "Name is 1 to 50 characters and unique per location; color is 1 to 64 characters. Stable Idempotency-Key required. Location-wide Standard v2 or OAuth operation. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name","color"],"properties":{"name":{"type":"string","maxLength":50},"color":{"type":"string","maxLength":64}}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/task-tags/{id}:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Read a task tag definition"
      description: "Returns one definition. Location-wide Standard v2 or OAuth operation. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."}}
    patch:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Update a task tag definition"
      description: "Renaming updates the definition only; matching with native behavior, names stored on tasks are not rewritten. Location-wide Standard v2 or OAuth operation. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":[],"properties":{"name":{"type":"string","maxLength":50},"color":{"type":"string","maxLength":64}}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}
    delete:
      x-seedly-oauth-scope: "tasks:delete"
      x-seedly-standard-scope: "tasks:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Delete a task tag definition"
      description: "Removes the definition atomically and returns jobId for the retained job that strips the name from tasks in bounded batches. Also requires task tag replacement and task job read/cancel approval. Recreating the same name stops that job. Location-wide Standard v2 or OAuth operation. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Receipt with jobId"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/task-bulk-jobs:
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Start a bulk task job"
      description: "Also needs task job read and cancel approval, so a caller can always watch and stop the job. Applies status, archive, restore, assign, due_date, priority or tags to 1 to 1000 distinct tasks in reauthorized batches of at most 25 tasks and 2 MiB. Tasks that cannot change are reported per item; completed work is never rolled back. Completing a task applies native dependency and subtask blockers. Assign also requires users:read. Linked contact and opportunity read approval is required for each changed task. Location-wide Standard v2 or OAuth operation. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["action","taskIds"],"properties":{"action":{"enum":["status","archive","restore","assign","due_date","priority","tags"]},"taskIds":{"type":"array","uniqueItems":true,"minItems":1,"maxItems":1000,"items":{"type":"string"}},"status":{"enum":["todo","in_review","completed","cancelled"]},"priority":{"enum":["low","medium","high","urgent"]},"assigneeIds":{"type":"array","maxItems":50,"items":{"type":"string"}},"mode":{"enum":["set","shift","add","remove"]},"dueDate":{"type":["integer","null"]},"shiftDays":{"type":"integer","minimum":-365,"maximum":365},"tags":{"type":"array","maxItems":100,"items":{"type":"string","maxLength":50}}}}}}}
      responses: {"200":{"description":"Job receipt"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/task-bulk-delete-jobs:
    post:
      x-seedly-oauth-scope: "tasks:delete"
      x-seedly-standard-scope: "tasks:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Start a bulk task delete job"
      description: "Linked contact and opportunity read approval and live pipeline access are required per task. Each deleted task sends task.deleted. A failing task is reported and later tasks continue. Also needs task job read and cancel approval, so a caller can always watch and stop the job. Permanently deletes 1 to 1000 distinct tasks and their child rows in reauthorized batches using the native cascade. Deleted tasks cannot be restored; cancel stops later batches only. Location-wide Standard v2 or OAuth operation. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["taskIds"],"properties":{"taskIds":{"type":"array","uniqueItems":true,"minItems":1,"maxItems":1000,"items":{"type":"string"}}}}}}}
      responses: {"200":{"description":"Job receipt"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/task-copy-jobs:
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Start a durable task copy job"
      description: "Also needs task job read and cancel approval, so a caller can always watch and stop the job. Copies 1 to 200 tasks without the synchronous subtask and assignee limits. Each transaction copies at most 100 subtasks or 50 assignees. A stopped job can leave a partial copy, listed in results. Copies follow native duplicate rules and exclude comments, dependencies, time entries and recurrence. Requires tasks:read and contact or opportunity read approval when the source is linked. Location-wide Standard v2 or OAuth operation. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["taskIds"],"properties":{"taskIds":{"type":"array","uniqueItems":true,"minItems":1,"maxItems":200,"items":{"type":"string"}},"options":{"type":"object","additionalProperties":false,"required":[],"properties":{"includeSubtasks":{"type":"boolean"},"includeAssignees":{"type":"boolean"},"includeTags":{"type":"boolean"},"includeDescription":{"type":"boolean"}}}}}}}}
      responses: {"200":{"description":"Job receipt"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/task-jobs/{id}:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Read task job progress"
      description: "Only the integration that started the job can read it. Returns counts, at most 50 failures with stable codes, created copy IDs, partial and stalled flags. No input or cursor is returned. Location-wide Standard v2 or OAuth operation. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."}}

  /api/v1/task-jobs/{id}/cancel:
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Cancel a task job"
      description: "Stops later batches. Completed batches stay in place and are reported as partial. Send an empty object. Location-wide Standard v2 or OAuth operation. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":[],"properties":{}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/task-jobs/{id}/resume:
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Resume a paused, cancelled or stalled task job"
      description: "Requires current authority for the job and replaces the persisted token ceiling with the current one. A running job with a live lease returns 409. Send an empty object. Location-wide Standard v2 or OAuth operation. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":[],"properties":{}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/projects:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "List projects"
      description: "Pages projects, optionally by status. Billing linkage is not returned. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Create a project"
      description: "Runs the native project-created workflow trigger and applies the location's active new_project template sets. An OAuth project records the consenting user; a location-wide key records no human creator. contactId needs contacts:read. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string","maxLength":200},"description":{"type":"string","maxLength":10000},"contactId":{"type":"string"},"planType":{"type":"string","maxLength":100}}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/projects/{id}:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Read a project"
      description: "Returns one project. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."}}
    patch:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Update a project"
      description: "Updates name, description or contact. Null contactId clears it. Use archive and restore for status. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":[],"properties":{"name":{"type":"string","maxLength":200},"description":{"type":"string","maxLength":10000},"contactId":{"type":["string","null"]}}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}
    delete:
      x-seedly-oauth-scope: "tasks:delete"
      x-seedly-standard-scope: "tasks:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Delete a project"
      description: "Linked contact and opportunity read approval and live pipeline access are required, otherwise the job pauses. Each deleted task sends task.deleted. Also needs task job read and cancel approval. Permanent. Returns jobId for a reauthorized job that deletes recurring rows, submissions, tasks and time entries in bounded batches, then the project. The project stays visible until its children are gone. Cancel stops later batches; deleted rows do not return. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Receipt with jobId"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/projects/{id}/archive:
    post:
      x-seedly-oauth-scope: "tasks:delete"
      x-seedly-standard-scope: "tasks:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Archive a project"
      description: "Requires tasks:delete, matching the native permission. Send an empty object. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":[],"properties":{}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/projects/{id}/restore:
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Restore an archived project"
      description: "Send an empty object. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":[],"properties":{}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/projects/{id}/time-summary:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Read project time totals"
      description: "Totals minutes by task from at most 1000 rows and 2 MB. capped is true when more rows exist. Task titles are not joined. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."}}

  /api/v1/time-entries:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "List time entries"
      description: "Newest first across the location. Accepts at most one of userId, taskId or projectId. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}},{"name":"userId","in":"query","required":false,"schema":{"type":"string"}},{"name":"taskId","in":"query","required":false,"schema":{"type":"string"}},{"name":"projectId","in":"query","required":false,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      tags: [Tasks]
      summary: "Log a manual time entry"
      description: "Duration rounds up to whole minutes, at most 525600. OAuth only: time belongs to a person, so the entry is recorded for the consenting user and a machine key has no one to attribute it to. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["title","durationMinutes"],"properties":{"title":{"type":"string","maxLength":500},"description":{"type":"string","maxLength":10000},"durationMinutes":{"type":"number"},"taskId":{"type":"string"},"projectId":{"type":"string"}}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/time-entries/{id}:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Read a time entry"
      description: "Returns one entry. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."}}
    patch:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      tags: [Tasks]
      summary: "Update your time entry"
      description: "Only the entry's own user can change it. OAuth only: time belongs to a person, so the entry is recorded for the consenting user and a machine key has no one to attribute it to. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":[],"properties":{"title":{"type":"string","maxLength":500},"description":{"type":"string","maxLength":10000},"durationMinutes":{"type":"number"}}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}
    delete:
      x-seedly-oauth-scope: "tasks:delete"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      tags: [Tasks]
      summary: "Delete your time entry"
      description: "Only the entry's own user can delete it. OAuth only: time belongs to a person, so the entry is recorded for the consenting user and a machine key has no one to attribute it to. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/time-entries/{id}/stop:
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      tags: [Tasks]
      summary: "Stop your running timer"
      description: "Only the timer's own user can stop it. Send an empty object. OAuth only: time belongs to a person, so the entry is recorded for the consenting user and a machine key has no one to attribute it to. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":[],"properties":{}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/time-entry-timers/current:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      tags: [Tasks]
      summary: "Read your running timer"
      description: "Returns the consenting user's running timer in this location, or null. OAuth only: time belongs to a person, so the entry is recorded for the consenting user and a machine key has no one to attribute it to. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."}}

  /api/v1/time-entry-timers:
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"]}
      tags: [Tasks]
      summary: "Start a timer"
      description: "A user has at most one running timer; a second returns 409. OAuth only: time belongs to a person, so the entry is recorded for the consenting user and a machine key has no one to attribute it to. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["title"],"properties":{"title":{"type":"string","maxLength":500},"taskId":{"type":"string"},"projectId":{"type":"string"}}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/task-template-sets:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "List task template sets"
      description: "Pages sets, including system sets. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Create a task template set"
      description: "A set with a non-manual trigger can create tasks automatically on later events. triggerRules is at most 16 KiB. productIds needs products:read. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name","triggerType"],"properties":{"name":{"type":"string","maxLength":200},"description":{"type":"string","maxLength":10000},"triggerType":{"enum":["manual","new_project","subscription_change","schedule"]},"triggerRules":{"type":"object"},"planTypes":{"type":"array","maxItems":50,"items":{"type":"string"}},"productIds":{"type":"array","uniqueItems":true,"maxItems":50,"items":{"type":"string"}},"active":{"type":"boolean"}}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/task-template-sets/{id}:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Read a task template set"
      description: "Returns one set. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."}}
    patch:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Update a task template set"
      description: "System sets return 409. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":[],"properties":{"name":{"type":"string","maxLength":200},"description":{"type":"string","maxLength":10000},"triggerType":{"enum":["manual","new_project","subscription_change","schedule"]},"triggerRules":{"type":"object"},"planTypes":{"type":"array","maxItems":50,"items":{"type":"string"}},"productIds":{"type":"array","uniqueItems":true,"maxItems":50,"items":{"type":"string"}},"active":{"type":"boolean"}}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}
    delete:
      x-seedly-oauth-scope: "tasks:delete"
      x-seedly-standard-scope: "tasks:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Delete a task template set"
      description: "Deletes the set with its templates in one transaction, at most 100 templates and 2000 subtasks; larger sets return 409 so templates can be deleted first. System sets return 409. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/task-template-sets/{id}/apply:
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Apply a template set to a project"
      description: "Also needs task job read and cancel approval. Starts a job creating one task per template, ten per batch, for at most 500 templates. Each batch rechecks the set, project and approval. Default assignees who left the location are skipped and counted. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["projectId"],"properties":{"projectId":{"type":"string"},"baseDate":{"type":"integer"}}}}}}
      responses: {"200":{"description":"Job receipt"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/task-template-sets/{id}/reorder:
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Reorder templates in a set"
      description: "Assigns positions from zero to 1 to 100 distinct templates. An ID outside the set fails the whole request. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["ids"],"properties":{"ids":{"type":"array","minItems":1,"maxItems":100,"uniqueItems":true,"items":{"type":"string"}}}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/task-templates:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "List task templates"
      description: "Pages templates, optionally by templateSetId. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}},{"name":"templateSetId","in":"query","required":false,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Create a task template"
      description: "defaultAssigneeIds needs users:read and current location access. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["title","templateType","dueInDays"],"properties":{"title":{"type":"string","maxLength":500},"description":{"type":"string","maxLength":10000},"templateType":{"enum":["onboarding","recurring","custom"]},"templateSetId":{"type":"string"},"defaultAssigneeIds":{"type":"array","uniqueItems":true,"maxItems":50,"items":{"type":"string"}},"dueInDays":{"type":"integer"},"estimatedMinutes":{"type":"integer"},"tags":{"type":"array","maxItems":100,"items":{"type":"string","maxLength":50}},"sortOrder":{"type":"integer"}}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/task-templates/{id}:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Read a task template"
      description: "Returns one template. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."}}
    patch:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Update a task template"
      description: "A template stays in its set; use the set reorder route to move it. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":[],"properties":{"title":{"type":"string","maxLength":500},"description":{"type":"string","maxLength":10000},"templateType":{"enum":["onboarding","recurring","custom"]},"defaultAssigneeIds":{"type":"array","uniqueItems":true,"maxItems":50,"items":{"type":"string"}},"dueInDays":{"type":"integer"},"estimatedMinutes":{"type":"integer"},"tags":{"type":"array","maxItems":100,"items":{"type":"string","maxLength":50}}}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}
    delete:
      x-seedly-oauth-scope: "tasks:delete"
      x-seedly-standard-scope: "tasks:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Delete a task template"
      description: "Deletes the template and up to 2000 subtasks in one transaction; larger templates return 409. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/task-templates/{id}/subtasks:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "List template subtasks"
      description: "Pages one template's subtasks. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Add a template subtask"
      description: "Appends unless sortOrder is supplied. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["title"],"properties":{"title":{"type":"string","maxLength":500},"sortOrder":{"type":"integer"}}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/task-templates/{id}/subtasks/{childId}:
    patch:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Update a template subtask"
      description: "The subtask must belong to the template. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"childId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":[],"properties":{"title":{"type":"string","maxLength":500},"sortOrder":{"type":"integer"}}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}
    delete:
      x-seedly-oauth-scope: "tasks:delete"
      x-seedly-standard-scope: "tasks:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Delete a template subtask"
      description: "The subtask must belong to the template. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"childId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/recurring-tasks:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "List recurring tasks"
      description: "Pages recurring task definitions, optionally by projectId. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}},{"name":"projectId","in":"query","required":false,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Create a recurring task"
      description: "A location can hold 200 active time-driven recurring tasks through this API; more returns 409. The native schedule creates tasks later. assigneeIds needs users:read. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["projectId","title","priority","frequency","dueInDays"],"properties":{"projectId":{"type":"string"},"title":{"type":"string","maxLength":500},"description":{"type":"string","maxLength":10000},"priority":{"enum":["low","medium","high","urgent"]},"tags":{"type":"array","maxItems":100,"items":{"type":"string","maxLength":50}},"estimatedMinutes":{"type":"integer"},"assigneeIds":{"type":"array","uniqueItems":true,"maxItems":50,"items":{"type":"string"}},"frequency":{"enum":["daily","weekly","biweekly","monthly"]},"dayOfWeek":{"type":"integer","minimum":0,"maximum":6},"dayOfMonth":{"type":"integer","minimum":1,"maximum":31},"dueInDays":{"type":"integer"}}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/recurring-tasks/{id}:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Read a recurring task"
      description: "Returns one definition, including paymentDriven. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."}}
    patch:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Update a recurring task"
      description: "Changing the schedule recalculates the next run. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":[],"properties":{"title":{"type":"string","maxLength":500},"description":{"type":"string","maxLength":10000},"priority":{"enum":["low","medium","high","urgent"]},"tags":{"type":"array","maxItems":100,"items":{"type":"string","maxLength":50}},"estimatedMinutes":{"type":"integer"},"assigneeIds":{"type":"array","uniqueItems":true,"maxItems":50,"items":{"type":"string"}},"frequency":{"enum":["daily","weekly","biweekly","monthly"]},"dayOfWeek":{"type":"integer","minimum":0,"maximum":6},"dayOfMonth":{"type":"integer","minimum":1,"maximum":31},"dueInDays":{"type":"integer"}}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}
    delete:
      x-seedly-oauth-scope: "tasks:delete"
      x-seedly-standard-scope: "tasks:delete"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Delete a recurring task"
      description: "Tasks already created are not affected. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/recurring-tasks/{id}/activate:
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Activate a recurring task"
      description: "The 200 active row limit applies. Explicit target state, so a retry cannot flip it back. Recalculates the next run. Send an empty object. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":[],"properties":{}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/recurring-tasks/{id}/deactivate:
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Deactivate a recurring task"
      description: "Explicit target state, so a retry cannot flip it back. Send an empty object. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":[],"properties":{}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/recurring-tasks/{id}/duplicate:
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Duplicate a recurring task"
      description: "The 200 active row limit applies. Keeps schedule and recurrence mode. Copied assignees need users:read. Send an empty object. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":[],"properties":{}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/task-submissions:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "List task submissions"
      description: "Newest first, optionally by status. The submission token is never returned. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string"}},{"name":"contactId","in":"query","required":false,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."}}
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Create a task submission"
      description: "Notifies the location's reviewers through the native path. Needs contacts:read. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["contactId","title","submittedBy"],"properties":{"contactId":{"type":"string"},"projectId":{"type":"string"},"title":{"type":"string","maxLength":500},"description":{"type":"string","maxLength":10000},"priority":{"enum":["low","medium","high","urgent"]},"submittedBy":{"type":"string","maxLength":200}}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/task-submissions/{id}:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Read a task submission"
      description: "Returns one submission. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."}}
    patch:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Update a task submission"
      description: "Changes triage fields before review. assigneeIds needs users:read. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":[],"properties":{"projectId":{"type":"string"},"priority":{"enum":["low","medium","high","urgent"]},"requestedDate":{"type":["integer","null"]},"assigneeIds":{"type":"array","uniqueItems":true,"maxItems":50,"items":{"type":"string"}}}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/task-submissions/{id}/approve:
    post:
      x-seedly-oauth-scope: "tasks:submissions:review"
      x-seedly-standard-scope: "tasks:submissions:review"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Approve a task submission"
      description: "Separate approval. Creates the task and can email the contact when the location has that email on. Needs contacts:read; assignees need users:read. The queued email rechecks authority and the review result before it is sent. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied. Refused for test credentials."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["projectId"],"properties":{"projectId":{"type":"string"},"assigneeIds":{"type":"array","uniqueItems":true,"maxItems":50,"items":{"type":"string"}},"dueDate":{"type":"integer"}}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/task-submissions/{id}/reject:
    post:
      x-seedly-oauth-scope: "tasks:submissions:review"
      x-seedly-standard-scope: "tasks:submissions:review"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Reject a task submission"
      description: "Separate approval. Can email the contact when the location has that email on. Needs contacts:read. reason is at most 500 characters. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied. Refused for test credentials."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":[],"properties":{"reason":{"type":"string","maxLength":500}}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/task-submissions/{id}/reopen:
    post:
      x-seedly-oauth-scope: "tasks:submissions:review"
      x-seedly-standard-scope: "tasks:submissions:review"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Reopen a rejected task submission"
      description: "Returns a rejected submission to pending. Sends nothing. Send an empty object. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":[],"properties":{}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/projects/{id}/task-counts:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Count tasks in a project"
      description: "Counts unarchived tasks by status from at most 1000 rows and 2 MB. capped is true when more exist. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."}}

  /api/v1/projects/{id}/tasks:
    post:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Create a task in a project"
      description: "Runs the native activity, contact timeline and task_added workflow effects. contactId needs contacts:read, dealId needs opportunities:read and live pipeline access, assigneeIds needs users:read. POST /api/v1/tasks is unchanged. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["title"],"properties":{"title":{"type":"string","maxLength":500},"description":{"type":"string","maxLength":10000},"status":{"enum":["todo","in_review","completed","cancelled"]},"priority":{"enum":["low","medium","high","urgent"]},"dueDate":{"type":"integer"},"tags":{"type":"array","maxItems":100,"items":{"type":"string","maxLength":50}},"estimatedMinutes":{"type":"integer"},"contactId":{"type":"string"},"dealId":{"type":"string"},"templateId":{"type":"string"},"assigneeIds":{"type":"array","uniqueItems":true,"maxItems":50,"items":{"type":"string"}}}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/tasks/{id}/activities:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "List task activity"
      description: "Newest first. Actor userId is null for a location-wide key. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}]
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."}}

  /api/v1/task-settings:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Read task settings"
      description: "Returns completion rules, default project and email switches. A null switch means the native default applies. Email template bindings and board layout are not included. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."}}
    patch:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Update task settings"
      description: "Changes only the supplied rules and email switches. defaultProjectId must be in this location; null clears it. Turning an email off stops that email for the whole location. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      parameters: [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":[],"properties":{"requireSubtaskCompletion":{"type":"boolean"},"requireDependencyCompletion":{"type":"boolean"},"pmTaskAssignedEmailEnabled":{"type":"boolean"},"pmTaskOverdueEmailEnabled":{"type":"boolean"},"pmTaskDueSoonEmailEnabled":{"type":"boolean"},"pmTaskSummaryEmailEnabled":{"type":"boolean"},"pmMentionEmailEnabled":{"type":"boolean"},"pmSubmissionApprovedEmailEnabled":{"type":"boolean"},"pmSubmissionRejectedEmailEnabled":{"type":"boolean"},"defaultProjectId":{"type":["string","null"]}}}}}}
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."},"409":{"description":"Conflicting state or reused Idempotency-Key."}}

  /api/v1/task-submission-stats:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      tags: [Tasks]
      summary: "Read submission counts"
      description: "Counts by status up to 1000 each. capped is true past that or when a read stops at its size limit; counts are then a floor. New exact operation approval is required; legacy API keys and own/team/selected record grants are denied."
      responses: {"200":{"description":"Success"},"400":{"description":"Invalid or oversized input."},"401":{"description":"Invalid credential."},"403":{"description":"Missing current authority."},"404":{"description":"Resource unavailable."},"429":{"description":"Rate limit exceeded."}}

  /api/v1/tasks/{id}/tags:
    get:
      x-seedly-oauth-scope: "tasks:read"
      x-seedly-standard-scope: "tasks:read"
      x-seedly-record-grant-approvals: {"minPolicyVersion":12,"options":["allowTaskMetadata"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: getTaskTags
      tags: [Tasks]
      summary: Read task tag membership
      description: "Exact new tasks:read route approval required. Standard v2 or OAuth only; legacy API keys are unchanged. Own/team/selected grants require version 12 allowTaskMetadata. Current task/project must remain in the bound tenant and task record grant. Reads do not fetch linked contact/deal content and require no additional related-record scopes. Returns only this task membership, never a location-wide PM tag catalog or contact tag data. Stored membership must fit the same count/length bounds; exact-string duplicates are collapsed, while preexisting empty tags remain readable."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]
      responses:
        '200':
          description: Authorized task membership or durable write receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["id","tags"],"properties":{"id":{"type":"string"},"tags":{"type":"array","maxItems":100,"uniqueItems":true,"items":{"type":"string","maxLength":50}}}}}}}}
        '400':
          description: Invalid payload, unsupported query, missing idempotency key or stored membership exceeds bounds.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, record or relationship outside current authority.
        '404':
          description: Unknown route.
        '409':
          description: Idempotency key reused with different request details.
        '429':
          description: Rate limit exceeded.
    put:
      x-seedly-oauth-scope: "tasks:write"
      x-seedly-standard-scope: "tasks:write"
      x-seedly-record-grant-approvals: {"minPolicyVersion":12,"options":["allowTaskMetadata"]}
      x-seedly-resource-restrictions: {"oauth":["location"],"standard":["location"]}
      operationId: replaceTaskTags
      tags: [Tasks]
      summary: Replace task tag membership
      description: "Exact new tasks:write route approval required. Standard v2 or OAuth only; legacy API keys are unchanged. Own/team/selected grants require version 12 allowTaskMetadata. Current task/project and related contact/deal records must remain in the bound tenant and within current record grants; linked records require their corresponding read scopes. Returns only this task membership, never a location-wide PM tag catalog or contact tag data. Replaces tags with at most 100 nonblank strings of at most 50 characters, using stable exact-string deduplication without case folding. An empty list clears membership. Requires Idempotency-Key. Changed membership preserves native update timestamps, activity and audit. Deferred task_updated workflow admission rechecks the original principal, effective OAuth scopes and current route, record and relationship permissions and pinned task, project, contact, deal and creator relationships before running configured workflows with the original bounded event payload. Revoked access or changed security relationships suppress effects; ordinary title, status or metadata edits do not discard an earlier authorized event. No-op replacements and receipt replays do not repeat these effects. Replays revalidate current authorization and relationships before returning the original receipt; they never reapply old tags. No PM tag catalog creation, bulk mutation or task duplication."
      parameters: [{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,128}$"}}]
      requestBody: {"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["tags"],"properties":{"tags":{"type":"array","maxItems":100,"items":{"type":"string","minLength":1,"maxLength":50}}}}}}}
      responses:
        '200':
          description: Authorized task membership or durable write receipt.
          content: {"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["id","updated"],"properties":{"id":{"type":"string"},"updated":{"const":true}}}}}}}
        '400':
          description: Invalid payload, unsupported query, missing idempotency key or stored membership exceeds bounds.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: Missing scope, stale approval, record or relationship outside current authority.
        '404':
          description: Unknown route.
        '409':
          description: Idempotency key reused with different request details.
        '429':
          description: Rate limit exceeded.
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: "API key, or opaque OAuth access token on supported connected-app routes"

  headers:
    X-API-Version:
      description: API version
      schema:
        type: string
        const: "v1"
    X-RateLimit-Limit:
      description: Total requests allowed in the current window
      schema:
        type: integer
    X-RateLimit-Remaining:
      description: Requests remaining in the current window
      schema:
        type: integer
    X-RateLimit-Reset:
      description: Unix timestamp (seconds) when the rate limit window resets
      schema:
        type: integer
    X-Sub-Account-Id:
      description: "Required for agency-scoped API keys. Specifies which sub-account to operate on."
      schema:
        type: string

  responses:
    Unauthorized:
      description: Authentication failed
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          examples:
            missing_header:
              value:
                error:
                  code: "UNAUTHORIZED"
                  message: "Missing Authorization header"
            invalid_key:
              value:
                error:
                  code: "UNAUTHORIZED"
                  message: "Invalid API key"
            key_revoked:
              value:
                error:
                  code: "KEY_REVOKED"
                  message: "API key has been revoked"
            key_expired:
              value:
                error:
                  code: "KEY_EXPIRED"
                  message: "API key has expired"

    Forbidden:
      description: Missing required scope
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            error:
              code: "FORBIDDEN"
              message: "API key missing required scope: contacts:read"

    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            error:
              code: "NOT_FOUND"
              message: "Contact not found"

    ValidationError:
      description: Invalid request
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            error:
              code: "VALIDATION_ERROR"
              message: "firstName and lastName are required"

    RateLimited:
      description: Rate limit exceeded
      headers:
        Retry-After:
          description: Seconds until the rate limit resets
          schema:
            type: integer
        X-RateLimit-Limit:
          $ref: "#/components/headers/X-RateLimit-Limit"
        X-RateLimit-Remaining:
          $ref: "#/components/headers/X-RateLimit-Remaining"
        X-RateLimit-Reset:
          $ref: "#/components/headers/X-RateLimit-Reset"
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            error:
              code: "RATE_LIMITED"
              message: "Too many requests"

    ExtensionRouteResult:
      description: |
        The add-on's answer, in the standard envelope. The CRM sets the status,
        the headers and the envelope; the add-on supplies only `data` and, if it
        chooses, `meta`.

        `data` is always present, `null` included: an add-on cannot produce a
        `200` with no `data` key. `meta` is emitted only when the add-on supplies
        an object; anything else is dropped rather than passed through. The
        serialised body is capped at 1 MB, and an add-on that exceeds it is
        reported as a `502` like any other handler failure.
      headers:
        X-API-Version:
          $ref: "#/components/headers/X-API-Version"
        X-RateLimit-Limit:
          $ref: "#/components/headers/X-RateLimit-Limit"
        X-RateLimit-Remaining:
          $ref: "#/components/headers/X-RateLimit-Remaining"
        X-RateLimit-Reset:
          $ref: "#/components/headers/X-RateLimit-Reset"
      content:
        application/json:
          schema:
            type: object
            required: [data]
            properties:
              data:
                description: Defined by the add-on. See `GET /api/v1/ext`.
              meta:
                type: object
                additionalProperties: true

    ExtensionHandlerFailed:
      description: |
        The add-on's handler failed. Nothing about the CRM or any other endpoint
        is affected, and no detail about the failure is returned; it is recorded
        in your Convex logs. Reported as 502 rather than 500 precisely so a
        broken add-on is distinguishable from a broken CRM.

        The one exception to 502 is narrow and deliberate: a handler that raises
        a structured validation rejection is answered `400 VALIDATION_ERROR`,
        because a bad request is never a 5xx. That 400 is a fixed body too. Every
        other failure, including one whose message happens to mention validation,
        is a 502.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            error:
              code: "INTERNAL_ERROR"
              message: "Extension route handler failed"

    ExtensionHandlerTimeout:
      description: |
        The add-on's handler did not answer within 10 seconds and was abandoned.
        Retrying is reasonable; a handler that consistently times out is a bug in
        the add-on.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            error:
              code: "INTERNAL_ERROR"
              message: "Extension route handler timed out"

  schemas:
    IntegrationCatalogProduct: {"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"name":{"type":"string","maxLength":1000},"description":{"type":["string","null"]},"price":{"type":"number"},"currency":{"type":"string","maxLength":10},"sku":{"type":["string","null"]},"category":{"type":["string","null"]},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","name","price","currency","isActive"]}
    AppointmentTypeCatalogCreate: {"type":"object","additionalProperties":false,"required":["name","slug","duration","color"],"properties":{"name":{"type":"string","minLength":1,"maxLength":250},"description":{"type":"string","maxLength":10000},"slug":{"type":"string","maxLength":100,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"},"duration":{"type":"integer","minimum":1,"maximum":1440},"color":{"type":"string","maxLength":100},"locationOptions":{"type":"array","maxItems":20,"items":{"type":"object","additionalProperties":false,"required":["type"],"properties":{"type":{"enum":["video","phone","in_person","custom","contact_address"]},"label":{"type":"string","maxLength":2000},"value":{"type":"string","maxLength":2000},"isDefault":{"type":"boolean"},"meetingLinkType":{"enum":["zoom","google_meet","none"]}}}},"bufferBefore":{"type":"integer","minimum":0,"maximum":1440},"bufferAfter":{"type":"integer","minimum":0,"maximum":1440},"maxPerDay":{"type":"integer","minimum":0,"maximum":100000},"maxSeats":{"type":"integer","minimum":0,"maximum":100000},"showAvailableSeats":{"type":"boolean"},"bookingFormId":{"type":"string"}}}
    AppointmentTypeCatalogUpdate: {"type":"object","additionalProperties":false,"minProperties":1,"properties":{"name":{"type":"string","minLength":1,"maxLength":250},"description":{"type":"string","maxLength":10000},"slug":{"type":"string","maxLength":100,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"},"duration":{"type":"integer","minimum":1,"maximum":1440},"color":{"type":"string","maxLength":100},"locationOptions":{"type":"array","maxItems":20,"items":{"type":"object","additionalProperties":false,"required":["type"],"properties":{"type":{"enum":["video","phone","in_person","custom","contact_address"]},"label":{"type":"string","maxLength":2000},"value":{"type":"string","maxLength":2000},"isDefault":{"type":"boolean"},"meetingLinkType":{"enum":["zoom","google_meet","none"]}}}},"bufferBefore":{"type":"integer","minimum":0,"maximum":1440},"bufferAfter":{"type":"integer","minimum":0,"maximum":1440},"maxPerDay":{"type":"integer","minimum":0,"maximum":100000},"maxSeats":{"type":"integer","minimum":0,"maximum":100000},"showAvailableSeats":{"type":"boolean"},"bookingFormId":{"type":"string"},"isActive":{"type":"boolean"},"clearBookingForm":{"type":"boolean"}}}
    AppointmentTypeCatalog: {"type":"object","additionalProperties":false,"required":["name","description","slug","duration","color","locationOptions","bufferBefore","bufferAfter","maxPerDay","maxSeats","showAvailableSeats","bookingFormId","id","calendarId","createdAt","isActive","updatedAt"],"properties":{"name":{"type":"string","minLength":1,"maxLength":250},"description":{"type":["string","null"]},"slug":{"type":"string","maxLength":100,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"},"duration":{"type":"integer","minimum":1,"maximum":1440},"color":{"type":"string","maxLength":100},"locationOptions":{"type":"array","maxItems":20,"items":{"type":"object","additionalProperties":false,"required":["type"],"properties":{"type":{"enum":["video","phone","in_person","custom","contact_address"]},"label":{"type":"string","maxLength":2000},"value":{"type":"string","maxLength":2000},"isDefault":{"type":"boolean"},"meetingLinkType":{"enum":["zoom","google_meet","none"]}}}},"bufferBefore":{"type":"integer","minimum":0,"maximum":1440},"bufferAfter":{"type":"integer","minimum":0,"maximum":1440},"maxPerDay":{"anyOf":[{"type":"integer","minimum":0,"maximum":100000},{"type":"null"}]},"maxSeats":{"anyOf":[{"type":"integer","minimum":0,"maximum":100000},{"type":"null"}]},"showAvailableSeats":{"type":"boolean"},"bookingFormId":{"anyOf":[{"type":"string"},{"type":"null"}]},"id":{"type":"string"},"calendarId":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"isActive":{"type":"boolean"},"updatedAt":{"type":"string","format":"date-time"}}}
    CalendarServiceCatalogCreate: {"type":"object","additionalProperties":false,"required":["name","duration"],"properties":{"name":{"type":"string","minLength":1,"maxLength":250},"description":{"type":"string","maxLength":10000},"duration":{"type":"integer","minimum":1,"maximum":1440},"categoryId":{"type":"string"},"price":{"type":"number","minimum":0,"maximum":1000000000.0,"description":"Major currency units. priceUnit must explicitly equal major when supplied."},"priceUnit":{"const":"major"},"currency":{"type":"string","pattern":"^[a-zA-Z]{3}$"},"color":{"type":"string","maxLength":100},"coverImage":{"type":"string","format":"uri","maxLength":2048,"description":"Public HTTPS asset URL only. No storage IDs or credential-bearing URLs."},"staffMembers":{"type":"array","maxItems":100,"uniqueItems":true,"items":{"type":"string"}},"sortOrder":{"type":"integer","minimum":0,"maximum":9007199254740991}}}
    CalendarServiceCatalogUpdate: {"type":"object","additionalProperties":false,"minProperties":1,"properties":{"name":{"type":"string","minLength":1,"maxLength":250},"description":{"type":"string","maxLength":10000},"duration":{"type":"integer","minimum":1,"maximum":1440},"categoryId":{"type":"string"},"price":{"type":"number","minimum":0,"maximum":1000000000.0,"description":"Major currency units. priceUnit must explicitly equal major when supplied."},"priceUnit":{"const":"major"},"currency":{"type":"string","pattern":"^[a-zA-Z]{3}$"},"color":{"type":"string","maxLength":100},"coverImage":{"type":"string","format":"uri","maxLength":2048,"description":"Public HTTPS asset URL only. No storage IDs or credential-bearing URLs."},"staffMembers":{"type":"array","maxItems":100,"uniqueItems":true,"items":{"type":"string"}},"sortOrder":{"type":"integer","minimum":0,"maximum":9007199254740991},"isActive":{"type":"boolean"},"clearCategory":{"type":"boolean"}}}
    CalendarServiceCatalog: {"type":"object","additionalProperties":false,"required":["name","description","duration","categoryId","price","priceUnit","currency","color","coverImage","staffMembers","sortOrder","id","calendarId","createdAt","isActive","updatedAt"],"properties":{"name":{"type":"string","minLength":1,"maxLength":250},"description":{"type":["string","null"]},"duration":{"type":"integer","minimum":1,"maximum":1440},"categoryId":{"anyOf":[{"type":"string"},{"type":"null"}]},"price":{"anyOf":[{"type":"number","minimum":0,"maximum":1000000000.0,"description":"Major currency units. priceUnit must explicitly equal major when supplied."},{"type":"null"}]},"priceUnit":{"const":"major"},"currency":{"type":"string","pattern":"^[a-zA-Z]{3}$"},"color":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}]},"coverImage":{"anyOf":[{"type":"string","format":"uri","maxLength":2048,"description":"Public HTTPS asset URL only. No storage IDs or credential-bearing URLs."},{"type":"null"}]},"staffMembers":{"type":"array","maxItems":100,"uniqueItems":true,"items":{"type":"string"}},"sortOrder":{"type":"integer","minimum":0,"maximum":9007199254740991},"id":{"type":"string"},"calendarId":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"isActive":{"type":"boolean"},"updatedAt":{"type":"string","format":"date-time"}}}
    ServiceCategoryCatalogCreate: {"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":250},"description":{"type":"string","maxLength":10000},"sortOrder":{"type":"integer","minimum":0,"maximum":9007199254740991}}}
    ServiceCategoryCatalogUpdate: {"type":"object","additionalProperties":false,"minProperties":1,"properties":{"name":{"type":"string","minLength":1,"maxLength":250},"description":{"type":"string","maxLength":10000},"sortOrder":{"type":"integer","minimum":0,"maximum":9007199254740991}}}
    ServiceCategoryCatalog: {"type":"object","additionalProperties":false,"required":["name","description","sortOrder","id","calendarId","createdAt"],"properties":{"name":{"type":"string","minLength":1,"maxLength":250},"description":{"type":["string","null"]},"sortOrder":{"type":"integer","minimum":0,"maximum":9007199254740991},"id":{"type":"string"},"calendarId":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}}
    ServiceCategoryDeletionJob: {"type":"object","additionalProperties":false,"required":["id","categoryId","calendarId","status","detached","skipped","stalled","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"categoryId":{"type":"string"},"calendarId":{"type":"string"},"status":{"enum":["running","paused","complete"]},"detached":{"type":"integer"},"skipped":{"type":"integer"},"stalled":{"type":"boolean"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}}

    OrganizationFolder: {"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"name":{"type":"string"},"parentId":{"type":["string","null"]},"sortOrder":{"type":"number"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","name","parentId","sortOrder","createdAt","updatedAt"]}
    OrganizationFolderDeletionJob: {"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"folderId":{"type":"string"},"status":{"enum":["running","paused","complete"]},"phase":{"enum":["records","folders"]},"recordsDetached":{"type":"integer"},"foldersDetached":{"type":"integer"},"skipped":{"type":"integer"},"failureCode":{"enum":["AUTHORITY_UNAVAILABLE",null]},"stalled":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","folderId","status","phase","recordsDetached","foldersDetached","skipped","failureCode","stalled","createdAt","updatedAt"]}
    PersonalNotificationPreferenceUpdate: {"type":"object","additionalProperties":false,"minProperties":1,"properties":{"preferences":{"type":"object","description":"Replacement event map. Keys must be advertised eventTypes; each entry contains all four channels. Empty map restores native missing-event defaults.","additionalProperties":{"type":"object","additionalProperties":false,"required":["email","inApp","push","sms"],"properties":{"email":{"type":"boolean"},"inApp":{"type":"boolean"},"push":{"type":"boolean"},"sms":{"type":"boolean"}}}},"digestEnabled":{"type":"boolean"},"digestFrequency":{"type":"string","enum":["instant","hourly","daily"]},"quietHoursEnabled":{"type":"boolean"},"quietHoursStart":{"type":"string","pattern":"^([01][0-9]|2[0-3]):[0-5][0-9]$"},"quietHoursEnd":{"type":"string","pattern":"^([01][0-9]|2[0-3]):[0-5][0-9]$"},"smsEnabled":{"type":"boolean"}}}
    PersonalNotificationPreferences: {"type":"object","additionalProperties":false,"minProperties":1,"properties":{"preferences":{"type":"object","description":"Replacement event map. Keys must be advertised eventTypes; each entry contains all four channels. Empty map restores native missing-event defaults.","additionalProperties":{"type":"object","additionalProperties":false,"required":["email","inApp","push","sms"],"properties":{"email":{"type":"boolean"},"inApp":{"type":"boolean"},"push":{"type":"boolean"},"sms":{"type":"boolean"}}}},"digestEnabled":{"type":"boolean"},"digestFrequency":{"type":"string","enum":["instant","hourly","daily"]},"quietHoursEnabled":{"type":"boolean"},"quietHoursStart":{"type":"string","pattern":"^([01][0-9]|2[0-3]):[0-5][0-9]$"},"quietHoursEnd":{"type":"string","pattern":"^([01][0-9]|2[0-3]):[0-5][0-9]$"},"smsEnabled":{"type":"boolean"},"eventTypes":{"type":"array","items":{"type":"string"}}},"required":["preferences","digestEnabled","digestFrequency","quietHoursEnabled","quietHoursStart","quietHoursEnd","smsEnabled","eventTypes"]}

    ContentAssetSnippetCreate: {"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":100},"content":{"type":"string","maxLength":10000},"channel":{"enum":["sms","email","any"]},"scope":{"enum":["conversation","bulk","both"]},"category":{"enum":["marketing","transactional","notification","other"]},"folder":{"type":"string","maxLength":50},"folderId":{"type":["string","null"]},"module":{"type":"string","maxLength":50},"shortcut":{"type":"string","maxLength":20}},"required":["name","content"]}
    ContentAssetSnippetUpdate: {"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":100},"content":{"type":"string","maxLength":10000},"channel":{"enum":["sms","email","any"]},"scope":{"enum":["conversation","bulk","both"]},"category":{"enum":["marketing","transactional","notification","other"]},"folder":{"type":"string","maxLength":50},"folderId":{"type":["string","null"]},"module":{"type":"string","maxLength":50},"shortcut":{"type":"string","maxLength":20}}}
    ContentAssetLibraryCreate: {"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":200},"description":{"type":"string","maxLength":2000},"category":{"enum":["layout","pricing","content","other"]},"blocks":{"type":"array","maxItems":100,"items":{"oneOf":[{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"heading"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"text":{"type":"string","maxLength":10000},"level":{"type":"integer","minimum":1,"maximum":3}},"required":["text"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"text"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"html":{"type":"string","maxLength":10000}},"required":["html"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"divider"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"style":{"enum":["solid","dashed","dotted"]}}}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"spacer"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"height":{"type":"number","minimum":0,"maximum":1000}},"required":["height"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"table_of_contents"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"depth":{"type":"integer","minimum":1,"maximum":6},"showPageNumbers":{"type":"boolean"}}}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"content_table"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"columns":{"type":"array","maxItems":12,"items":{"type":"string","maxLength":1000}},"rows":{"type":"array","maxItems":100,"items":{"type":"array","items":{"type":"string","maxLength":2000}}},"showHeader":{"type":"boolean"}},"required":["columns","rows"]}},"required":["id","type","data"]}]}}},"required":["name","blocks"]}
    ContentAssetAdvancedLibraryCreate: {"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":200},"description":{"type":"string","maxLength":2000},"category":{"enum":["layout","pricing","content","other"]},"blocks":{"type":"array","maxItems":100,"items":{"oneOf":[{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"heading"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"text":{"type":"string","maxLength":10000},"level":{"type":"integer","minimum":1,"maximum":3}},"required":["text"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"text"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"html":{"type":"string","maxLength":10000}},"required":["html"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"divider"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"style":{"enum":["solid","dashed","dotted"]}}}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"spacer"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"height":{"type":"number","minimum":0,"maximum":1000}},"required":["height"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"table_of_contents"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"depth":{"type":"integer","minimum":1,"maximum":6},"showPageNumbers":{"type":"boolean"}}}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"content_table"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"columns":{"type":"array","maxItems":12,"items":{"type":"string","maxLength":1000}},"rows":{"type":"array","maxItems":100,"items":{"type":"array","items":{"type":"string","maxLength":2000}}},"showHeader":{"type":"boolean"}},"required":["columns","rows"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"pricing_table"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","maxItems":100,"items":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":1000},"description":{"type":"string","maxLength":4000},"quantity":{"type":"number","minimum":0,"maximum":1000000},"unitPrice":{"type":"number","minimum":0,"maximum":1000000000},"amount":{"type":"number","minimum":0,"maximum":1000000000},"productId":{"type":"string","maxLength":100}},"required":["quantity","unitPrice"],"anyOf":[{"required":["name"]},{"required":["description"]}]}},"taxRate":{"type":"number","minimum":0,"maximum":100},"taxes":{"type":"array","maxItems":10,"items":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":100},"rate":{"type":"number","minimum":0,"maximum":100}},"required":["rate"]}},"discountType":{"enum":["","percent","percentage","fixed"]},"discountValue":{"type":"number","minimum":0,"maximum":1000000000}},"required":["items"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"line_items"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","maxItems":100,"items":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":1000},"description":{"type":"string","maxLength":4000},"quantity":{"type":"number","minimum":0,"maximum":1000000},"unitPrice":{"type":"number","minimum":0,"maximum":1000000000},"amount":{"type":"number","minimum":0,"maximum":1000000000},"productId":{"type":"string","maxLength":100}},"required":["quantity","unitPrice"],"anyOf":[{"required":["name"]},{"required":["description"]}]}},"label":{"type":"string","maxLength":1000}},"required":["items"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"optional_items"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","maxItems":100,"items":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":1000},"description":{"type":"string","maxLength":4000},"quantity":{"type":"number","minimum":0,"maximum":1000000},"unitPrice":{"type":"number","minimum":0,"maximum":1000000000},"amount":{"type":"number","minimum":0,"maximum":1000000000},"productId":{"type":"string","maxLength":100}},"required":["quantity","unitPrice"],"anyOf":[{"required":["name"]},{"required":["description"]}]}},"label":{"type":"string","maxLength":1000}},"required":["items"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"package_group"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"label":{"type":"string","maxLength":1000},"description":{"type":"string","maxLength":4000},"packages":{"type":"array","maxItems":20,"items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"name":{"type":"string","maxLength":1000},"description":{"type":"string","maxLength":4000},"items":{"type":"array","maxItems":100,"items":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":1000},"description":{"type":"string","maxLength":4000},"quantity":{"type":"number","minimum":0,"maximum":1000000},"unitPrice":{"type":"number","minimum":0,"maximum":1000000000},"amount":{"type":"number","minimum":0,"maximum":1000000000},"productId":{"type":"string","maxLength":100}},"required":["quantity","unitPrice"],"anyOf":[{"required":["name"]},{"required":["description"]}]}}},"required":["id","name","items"]}}},"required":["packages"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"picker_single"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"label":{"type":"string","maxLength":1000},"options":{"type":"array","maxItems":100,"uniqueItems":true,"items":{"type":"string","maxLength":1000}},"required":{"type":"boolean"}},"required":["label","options"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"picker_multiple"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"label":{"type":"string","maxLength":1000},"options":{"type":"array","maxItems":100,"uniqueItems":true,"items":{"type":"string","maxLength":1000}},"required":{"type":"boolean"}},"required":["label","options"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"terms"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"html":{"type":"string","maxLength":10000},"requireAcceptance":{"type":"boolean"}},"required":["html"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"signature"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"label":{"type":"string","maxLength":1000}},"required":["label"]}},"required":["id","type","data"]}]}}},"required":["name","blocks"]}
    ContentAssetLibraryUpdate: {"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":200},"description":{"type":"string","maxLength":2000},"category":{"enum":["layout","pricing","content","other"]},"blocks":{"type":"array","maxItems":100,"items":{"oneOf":[{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"heading"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"text":{"type":"string","maxLength":10000},"level":{"type":"integer","minimum":1,"maximum":3}},"required":["text"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"text"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"html":{"type":"string","maxLength":10000}},"required":["html"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"divider"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"style":{"enum":["solid","dashed","dotted"]}}}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"spacer"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"height":{"type":"number","minimum":0,"maximum":1000}},"required":["height"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"table_of_contents"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"depth":{"type":"integer","minimum":1,"maximum":6},"showPageNumbers":{"type":"boolean"}}}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"content_table"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"columns":{"type":"array","maxItems":12,"items":{"type":"string","maxLength":1000}},"rows":{"type":"array","maxItems":100,"items":{"type":"array","items":{"type":"string","maxLength":2000}}},"showHeader":{"type":"boolean"}},"required":["columns","rows"]}},"required":["id","type","data"]}]}}}}
    ContentAssetAdvancedLibraryUpdate: {"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":200},"description":{"type":"string","maxLength":2000},"category":{"enum":["layout","pricing","content","other"]},"blocks":{"type":"array","maxItems":100,"items":{"oneOf":[{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"heading"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"text":{"type":"string","maxLength":10000},"level":{"type":"integer","minimum":1,"maximum":3}},"required":["text"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"text"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"html":{"type":"string","maxLength":10000}},"required":["html"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"divider"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"style":{"enum":["solid","dashed","dotted"]}}}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"spacer"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"height":{"type":"number","minimum":0,"maximum":1000}},"required":["height"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"table_of_contents"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"depth":{"type":"integer","minimum":1,"maximum":6},"showPageNumbers":{"type":"boolean"}}}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"content_table"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"columns":{"type":"array","maxItems":12,"items":{"type":"string","maxLength":1000}},"rows":{"type":"array","maxItems":100,"items":{"type":"array","items":{"type":"string","maxLength":2000}}},"showHeader":{"type":"boolean"}},"required":["columns","rows"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"pricing_table"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","maxItems":100,"items":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":1000},"description":{"type":"string","maxLength":4000},"quantity":{"type":"number","minimum":0,"maximum":1000000},"unitPrice":{"type":"number","minimum":0,"maximum":1000000000},"amount":{"type":"number","minimum":0,"maximum":1000000000},"productId":{"type":"string","maxLength":100}},"required":["quantity","unitPrice"],"anyOf":[{"required":["name"]},{"required":["description"]}]}},"taxRate":{"type":"number","minimum":0,"maximum":100},"taxes":{"type":"array","maxItems":10,"items":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":100},"rate":{"type":"number","minimum":0,"maximum":100}},"required":["rate"]}},"discountType":{"enum":["","percent","percentage","fixed"]},"discountValue":{"type":"number","minimum":0,"maximum":1000000000}},"required":["items"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"line_items"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","maxItems":100,"items":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":1000},"description":{"type":"string","maxLength":4000},"quantity":{"type":"number","minimum":0,"maximum":1000000},"unitPrice":{"type":"number","minimum":0,"maximum":1000000000},"amount":{"type":"number","minimum":0,"maximum":1000000000},"productId":{"type":"string","maxLength":100}},"required":["quantity","unitPrice"],"anyOf":[{"required":["name"]},{"required":["description"]}]}},"label":{"type":"string","maxLength":1000}},"required":["items"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"optional_items"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","maxItems":100,"items":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":1000},"description":{"type":"string","maxLength":4000},"quantity":{"type":"number","minimum":0,"maximum":1000000},"unitPrice":{"type":"number","minimum":0,"maximum":1000000000},"amount":{"type":"number","minimum":0,"maximum":1000000000},"productId":{"type":"string","maxLength":100}},"required":["quantity","unitPrice"],"anyOf":[{"required":["name"]},{"required":["description"]}]}},"label":{"type":"string","maxLength":1000}},"required":["items"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"package_group"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"label":{"type":"string","maxLength":1000},"description":{"type":"string","maxLength":4000},"packages":{"type":"array","maxItems":20,"items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"name":{"type":"string","maxLength":1000},"description":{"type":"string","maxLength":4000},"items":{"type":"array","maxItems":100,"items":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":1000},"description":{"type":"string","maxLength":4000},"quantity":{"type":"number","minimum":0,"maximum":1000000},"unitPrice":{"type":"number","minimum":0,"maximum":1000000000},"amount":{"type":"number","minimum":0,"maximum":1000000000},"productId":{"type":"string","maxLength":100}},"required":["quantity","unitPrice"],"anyOf":[{"required":["name"]},{"required":["description"]}]}}},"required":["id","name","items"]}}},"required":["packages"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"picker_single"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"label":{"type":"string","maxLength":1000},"options":{"type":"array","maxItems":100,"uniqueItems":true,"items":{"type":"string","maxLength":1000}},"required":{"type":"boolean"}},"required":["label","options"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"picker_multiple"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"label":{"type":"string","maxLength":1000},"options":{"type":"array","maxItems":100,"uniqueItems":true,"items":{"type":"string","maxLength":1000}},"required":{"type":"boolean"}},"required":["label","options"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"terms"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"html":{"type":"string","maxLength":10000},"requireAcceptance":{"type":"boolean"}},"required":["html"]}},"required":["id","type","data"]},{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","maxLength":100},"type":{"const":"signature"},"width":{"enum":["full","1/2","1/3","1/4","2/3","3/4"]},"data":{"type":"object","additionalProperties":false,"properties":{"label":{"type":"string","maxLength":1000}},"required":["label"]}},"required":["id","type","data"]}]}}}}
    ContentAssetFolderCreate: {"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":50},"parentId":{"type":["string","null"]}},"required":["name"]}
    ContentAssetFolderUpdate: {"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":50}},"required":["name"]}
    AudienceFilterRule: {"type":"object","additionalProperties":false,"required":["field","operator","value"],"properties":{"field":{"type":"string"},"operator":{"type":"string"},"value":{"type":"string","maxLength":2000},"type":{"type":"string","const":"rule"}}}
    AudienceFilterGroup: {"type":"object","additionalProperties":false,"required":["type","logic","children"],"properties":{"type":{"const":"group"},"logic":{"enum":["and","or"]},"negate":{"type":"boolean"},"children":{"type":"array","minItems":1,"maxItems":100,"items":{"oneOf":[{"$ref":"#/components/schemas/AudienceFilterRule"},{"$ref":"#/components/schemas/AudienceFilterGroup"}]}}}}
    AudienceFilter: {"oneOf":[{"type":"array","minItems":1,"maxItems":100,"items":{"$ref":"#/components/schemas/AudienceFilterRule"}},{"$ref":"#/components/schemas/AudienceFilterGroup"},{"type":"object","required":["groups"],"additionalProperties":false,"properties":{"groups":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"object","required":["rules"],"additionalProperties":false,"properties":{"rules":{"type":"array","minItems":1,"maxItems":100,"items":{"$ref":"#/components/schemas/AudienceFilterRule"}}}}}}}]}
    ContactListDefinition: {"type":"object","additionalProperties":false,"required":["id","name","description","membershipMode","isTransactional","filterCriteria","filterRedacted","filterRedactedReason","sortOrder","archivedAt","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"membershipMode":{"enum":["manual","filter","opt-in"]},"isTransactional":{"type":"boolean"},"filterCriteria":{"oneOf":[{"$ref":"#/components/schemas/AudienceFilter"},{"type":"null"}]},"filterRedacted":{"type":"boolean"},"filterRedactedReason":{"type":["string","null"],"enum":["hidden_pipeline","unsupported_filter",null]},"sortOrder":{"type":"number"},"archivedAt":{"type":["number","null"]},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}}}
    AudienceSegment: {"type":"object","additionalProperties":false,"required":["id","name","description","filterCriteria","folderId","contactCount","contactCountApproximate","filterRedacted","filterRedactedReason","lastRefreshedAt","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"filterCriteria":{"oneOf":[{"$ref":"#/components/schemas/AudienceFilter"},{"type":"null"}]},"folderId":{"type":["string","null"]},"contactCount":{"type":["number","null"]},"contactCountApproximate":{"type":["boolean","null"]},"filterRedacted":{"type":"boolean"},"filterRedactedReason":{"type":["string","null"],"enum":["hidden_pipeline","unsupported_filter",null]},"lastRefreshedAt":{"type":["number","null"]},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}}}
    AudienceSegmentFolder: {"type":"object","additionalProperties":false,"required":["id","name","parentId","sortOrder","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"parentId":{"type":["string","null"]},"sortOrder":{"type":"number"},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}}}
    AudienceContactReference: {"type":"object","additionalProperties":false,"required":["contactId"],"properties":{"contactId":{"type":"string"}}}
    AudienceWriteReceipt: {"type":"object","additionalProperties":false,"required":["id","created","updated"],"properties":{"id":{"type":"string"},"created":{"type":"boolean"},"updated":{"type":"boolean"},"deleted":{"type":"boolean"}}}
    CallHistoryDetail: {"type": "object", "additionalProperties": false, "required": ["id", "contactId", "direction", "outcome", "notes", "callerNumber", "calledNumber", "dispositionId", "dispositionLabel", "duration", "calledAt", "createdAt"], "properties": {"id": {"type": "string"}, "contactId": {"type": "string"}, "direction": {"type": "string"}, "outcome": {"type": "string"}, "notes": {"type": ["string", "null"]}, "callerNumber": {"type": ["string", "null"]}, "calledNumber": {"type": ["string", "null"]}, "dispositionId": {"type": ["string", "null"]}, "dispositionLabel": {"type": ["string", "null"]}, "duration": {"type": ["number", "null"]}, "calledAt": {"type": "string", "format": "date-time"}, "createdAt": {"type": "string", "format": "date-time"}}}
    CallHistoryEntry:
      {
        'type': 'object',
        'additionalProperties': false,
        'required':
          [
            'id',
            'contactId',
            'direction',
            'duration',
            'outcome',
            'callerNumber',
            'calledNumber',
            'dispositionId',
            'dispositionLabel',
            'calledAt',
            'createdAt',
          ],
        'properties':
          {
            'id': { 'type': 'string' },
            'contactId': { 'type': 'string' },
            'direction': { 'type': 'string' },
            'outcome': { 'type': 'string' },
            'duration': { 'type': ['number', 'null'] },
            'callerNumber': { 'type': ['string', 'null'] },
            'calledNumber': { 'type': ['string', 'null'] },
            'dispositionId': { 'type': ['string', 'null'] },
            'dispositionLabel': { 'type': ['string', 'null'] },
            'calledAt': { 'type': 'string', 'format': 'date-time' },
            'createdAt': { 'type': 'string', 'format': 'date-time' },
          },
      }
    CallRecordingEntry:
      {
        'type': 'object',
        'additionalProperties': false,
        'required':
          [
            'id',
            'source',
            'callLogId',
            'contactId',
            'duration',
            'status',
            'createdAt',
            'retainUntil',
          ],
        'properties':
          {
            'id': { 'type': 'string' },
            'callLogId': { 'type': 'string' },
            'contactId': { 'type': 'string' },
            'status': { 'type': 'string' },
            'source': { 'type': 'string', 'enum': ['native', 'app'] },
            'duration': { 'type': ['number', 'null'] },
            'createdAt': { 'type': 'string', 'format': 'date-time' },
            'retainUntil': { 'type': ['string', 'null'], 'format': 'date-time' },
          },
      }
    CallTranscriptSummary:
      {
        'type': 'object',
        'required':
          [
            'id',
            'source',
            'callLogId',
            'contactId',
            'recordingId',
            'language',
            'status',
            'createdAt',
          ],
        'properties':
          {
            'id': { 'type': 'string' },
            'callLogId': { 'type': 'string' },
            'contactId': { 'type': 'string' },
            'source': { 'type': 'string', 'enum': ['native', 'app'] },
            'recordingId': { 'type': ['string', 'null'] },
            'language': { 'type': ['string', 'null'] },
            'status': { 'type': 'string', 'const': 'completed' },
            'createdAt': { 'type': 'string', 'format': 'date-time' },
          },
      }
    CallLibraryPage:
      {
        'type': 'object',
        'required': ['limit', 'hasMore', 'nextCursor'],
        'properties':
          {
            'limit': { 'type': 'integer', 'minimum': 1, 'maximum': 50 },
            'hasMore': { 'type': 'boolean' },
            'nextCursor': { 'type': ['string', 'null'] },
          },
      }
    CallDispositionResponse:
      {
        'type': 'object',
        'required': ['data', 'meta'],
        'properties':
          {
            'data':
              {
                'type': 'array',
                'maxItems': 200,
                'items':
                  {
                    'type': 'object',
                    'required': ['id', 'label', 'color'],
                    'properties':
                      {
                        'id': { 'type': ['string', 'null'] },
                        'label': { 'type': 'string' },
                        'color': { 'type': ['string', 'null'] },
                      },
                  },
              },
            'meta':
              {
                'type': 'object',
                'properties': { 'configured': { 'type': 'boolean' } },
                'required': ['configured'],
              },
          },
      }
    CallTranscriptDetail:
      {
        'allOf':
          [
            { '$ref': '#/components/schemas/CallTranscriptSummary' },
            {
              'type': 'object',
              'required': ['text', 'segments'],
              'properties':
                {
                  'text': { 'type': 'string' },
                  'segments':
                    {
                      'type': 'array',
                      'maxItems': 5000,
                      'items':
                        {
                          'type': 'object',
                          'required': ['speaker', 'text', 'startMs', 'endMs'],
                          'properties':
                            {
                              'speaker': { 'type': 'string' },
                              'text': { 'type': 'string' },
                              'startMs': { 'type': 'number' },
                              'endMs': { 'type': 'number' },
                            },
                        },
                    },
                },
            },
          ],
      }
    CallHistoryList:
      {
        'type': 'object',
        'required': ['data', 'meta'],
        'properties':
          {
            'data':
              {
                'type': 'array',
                'maxItems': 50,
                'items': { '$ref': '#/components/schemas/CallHistoryEntry' },
              },
            'meta': { '$ref': '#/components/schemas/CallLibraryPage' },
          },
      }
    CallHistoryResponse:
      {
        'type': 'object',
        'required': ['data'],
        'properties': { 'data': { '$ref': '#/components/schemas/CallHistoryDetail' } },
      }
    CallRecordingList:
      {
        'type': 'object',
        'required': ['data', 'meta'],
        'properties':
          {
            'data':
              {
                'type': 'array',
                'maxItems': 50,
                'items': { '$ref': '#/components/schemas/CallRecordingEntry' },
              },
            'meta': { '$ref': '#/components/schemas/CallLibraryPage' },
          },
      }
    CallRecordingResponse:
      {
        'type': 'object',
        'required': ['data'],
        'properties': { 'data': { '$ref': '#/components/schemas/CallRecordingEntry' } },
      }
    CallTranscriptList:
      {
        'type': 'object',
        'required': ['data', 'meta'],
        'properties':
          {
            'data':
              {
                'type': 'array',
                'maxItems': 50,
                'items': { '$ref': '#/components/schemas/CallTranscriptSummary' },
              },
            'meta': { '$ref': '#/components/schemas/CallLibraryPage' },
          },
      }
    CallTranscriptResponse:
      {
        'type': 'object',
        'required': ['data'],
        'properties': { 'data': { '$ref': '#/components/schemas/CallTranscriptDetail' } },
      }
    FormField: {"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"type":"string"},"label":{"type":"string"},"placeholder":{"anyOf":[{"type":"string"},{"type":"null"}]},"required":{"type":"boolean"},"options":{"type":"array","items":{"type":"string"}},"validation":{},"conditionalLogic":{},"contactFieldMapping":{"anyOf":[{"type":"string"},{"type":"null"}]},"crmBinding":{},"defaultValue":{"anyOf":[{"type":"string"},{"type":"null"}]},"width":{"type":"string"},"helpText":{"type":"string"},"checkboxText":{"type":"string"},"labelAlignment":{"type":"string"},"styleOverrides":{},"ratingMin":{"type":"number"},"ratingMax":{"type":"number"},"npsMin":{"type":"number"},"npsMax":{"type":"number"},"matrixRows":{"type":"array","items":{"type":"string"}},"matrixColumns":{"type":"array","items":{"type":"string"}},"rankingItems":{"type":"array","items":{"type":"string"}},"imageUrl":{"type":"string"},"imageAlt":{"type":"string"},"listSubscription":{},"isHidden":{"type":"boolean"}},"required":["id","type","label","required"]}
    FormPage: {"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"fieldIds":{"type":"array","items":{"type":"string"}},"belowButtonFieldIds":{"type":"array","items":{"type":"string"}},"navigation":{}},"required":["id","title","fieldIds"]}
    FormTheme: {"type":"object","additionalProperties":false,"properties":{"showLabels":{"type":"boolean"},"showHelpText":{"type":"boolean"},"showRequiredAsterisk":{"type":"boolean"},"primaryColor":{"type":"string"},"globalFontFamily":{"type":"string"},"globalSpacing":{"type":"number"},"surface":{"enum":["light","dark"]},"containerBg":{"type":"string"},"containerBorderColor":{"type":"string"},"containerBorderRadius":{"type":"number"},"containerBorderWidth":{"type":"number"},"containerShadow":{"type":"boolean"},"containerShadowIntensity":{"type":"number"},"containerPadding":{"type":"number"},"containerPaddingTop":{"type":"number"},"containerPaddingBottom":{"type":"number"},"containerPaddingLeft":{"type":"number"},"containerPaddingRight":{"type":"number"},"containerMaxWidth":{"type":"string"},"containerWidth":{"type":"number"},"inputs":{},"button":{},"checkboxRadio":{},"success":{},"labels":{},"helpText":{},"customCss":{"type":"string"},"container":{},"submitButton":{},"input":{},"label":{},"successMessage":{},"checkbox":{},"radio":{},"pageNavigation":{}}}
    FormPresentation: {"type":"object","additionalProperties":false,"properties":{"compliance":{"type":"object","additionalProperties":false,"properties":{"enabled":{"type":"boolean"},"companyName":{"type":"string"},"companyWebsite":{"type":"string"},"privacyPolicyUrl":{"type":"string"},"termsUrl":{"type":"string"},"footerHtml":{"type":"string"},"smsConsentText":{"type":"string"},"marketingConsentText":{"type":"string"}}},"successElements":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"enum":["heading","textContent","html","image","divider"]},"label":{"type":"string"},"defaultValue":{"anyOf":[{"type":"string"},{"type":"null"}]},"placeholder":{"anyOf":[{"type":"string"},{"type":"null"}]},"required":{"type":"boolean"},"imageUrl":{"type":"string"},"imageAlt":{"type":"string"},"width":{"type":"string"},"styleOverrides":{}},"required":["id","type"]}},"redirectUrl":{"type":"string"},"successMessage":{"type":"string"},"thankYouMessage":{"type":"string"},"submitButtonText":{"type":"string"},"embedType":{"enum":["inline","popup","sticky_sidebar","slide_in"]},"trackViews":{"type":"boolean"},"showPoweredBy":{"type":"boolean"},"allowUrlPrefill":{"type":"boolean"}}}
    FormAutomation: {"type":"object","additionalProperties":false,"properties":{"notificationEmails":{"type":"array","items":{"type":"string","format":"email"},"maxItems":20},"notifyViaInternal":{"type":"boolean"},"autoResponderEnabled":{"type":"boolean"},"autoResponderSubject":{"type":"string"},"autoResponderBody":{"type":"string"},"autoResponderCooldownMinutes":{"type":"number"},"subscribeNewContactsToDefaultLists":{"type":"boolean"},"autoCreateDeal":{"type":"boolean"},"autoCreateDealPipelineId":{"anyOf":[{"type":"string","description":"pipelines identifier."},{"type":"null"}]},"autoCreateDealStageId":{"anyOf":[{"type":"string","description":"pipelineStages identifier."},{"type":"null"}]},"autoCreateDealAdLeadsOnly":{"type":"boolean"},"webhookEnabled":{"type":"boolean"},"doubleOptInEnabled":{"type":"boolean"},"doubleOptInListId":{"anyOf":[{"type":"string","description":"emailCategories identifier."},{"type":"null"}]},"doubleOptInConfirmSubject":{"type":"string"},"doubleOptInConfirmHeading":{"type":"string"},"doubleOptInConfirmBody":{"type":"string"},"doubleOptInConfirmRedirectUrl":{"type":"string"},"signedSubmissions":{"type":"object","additionalProperties":false,"properties":{"enabled":{"type":"boolean"},"signerCopyEnabled":{"type":"boolean"},"signerCopySubject":{"type":"string"},"signerCopyIntro":{"type":"string"},"oneSignedSubmissionPerContact":{"type":"boolean"}}}},"minProperties":1}
    FormCreate: {"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":250},"description":{"type":"string","maxLength":10000},"folderId":{"type":"string","description":"formFolders identifier."}},"required":["name"]}
    FormUpdate: {"type":"object","additionalProperties":false,"properties":{"name":{"type":"string"},"description":{"type":"string"},"settings":{"type":"object","additionalProperties":false,"properties":{"compliance":{"type":"object","additionalProperties":false,"properties":{"enabled":{"type":"boolean"},"companyName":{"type":"string"},"companyWebsite":{"type":"string"},"privacyPolicyUrl":{"type":"string"},"termsUrl":{"type":"string"},"footerHtml":{"type":"string"},"smsConsentText":{"type":"string"},"marketingConsentText":{"type":"string"}}},"successElements":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"enum":["heading","textContent","html","image","divider"]},"label":{"type":"string"},"defaultValue":{"anyOf":[{"type":"string"},{"type":"null"}]},"placeholder":{"anyOf":[{"type":"string"},{"type":"null"}]},"required":{"type":"boolean"},"imageUrl":{"type":"string"},"imageAlt":{"type":"string"},"width":{"type":"string"},"styleOverrides":{}},"required":["id","type"]}},"redirectUrl":{"type":"string"},"successMessage":{"type":"string"},"thankYouMessage":{"type":"string"},"submitButtonText":{"type":"string"},"embedType":{"enum":["inline","popup","sticky_sidebar","slide_in"]},"trackViews":{"type":"boolean"},"showPoweredBy":{"type":"boolean"},"allowUrlPrefill":{"type":"boolean"}}},"schema":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"type":"string"},"label":{"type":"string"},"placeholder":{"anyOf":[{"type":"string"},{"type":"null"}]},"required":{"type":"boolean"},"options":{"type":"array","items":{"type":"string"}},"validation":{},"conditionalLogic":{},"contactFieldMapping":{"anyOf":[{"type":"string"},{"type":"null"}]},"crmBinding":{},"defaultValue":{"anyOf":[{"type":"string"},{"type":"null"}]},"width":{"type":"string"},"helpText":{"type":"string"},"checkboxText":{"type":"string"},"labelAlignment":{"type":"string"},"styleOverrides":{},"ratingMin":{"type":"number"},"ratingMax":{"type":"number"},"npsMin":{"type":"number"},"npsMax":{"type":"number"},"matrixRows":{"type":"array","items":{"type":"string"}},"matrixColumns":{"type":"array","items":{"type":"string"}},"rankingItems":{"type":"array","items":{"type":"string"}},"imageUrl":{"type":"string"},"imageAlt":{"type":"string"},"listSubscription":{},"isHidden":{"type":"boolean"}},"required":["id","type","label","required"]},"maxItems":200},"theme":{"anyOf":[{"type":"object","additionalProperties":false,"properties":{"showLabels":{"type":"boolean"},"showHelpText":{"type":"boolean"},"showRequiredAsterisk":{"type":"boolean"},"primaryColor":{"type":"string"},"globalFontFamily":{"type":"string"},"globalSpacing":{"type":"number"},"surface":{"enum":["light","dark"]},"containerBg":{"type":"string"},"containerBorderColor":{"type":"string"},"containerBorderRadius":{"type":"number"},"containerBorderWidth":{"type":"number"},"containerShadow":{"type":"boolean"},"containerShadowIntensity":{"type":"number"},"containerPadding":{"type":"number"},"containerPaddingTop":{"type":"number"},"containerPaddingBottom":{"type":"number"},"containerPaddingLeft":{"type":"number"},"containerPaddingRight":{"type":"number"},"containerMaxWidth":{"type":"string"},"containerWidth":{"type":"number"},"inputs":{},"button":{},"checkboxRadio":{},"success":{},"labels":{},"helpText":{},"customCss":{"type":"string"},"container":{},"submitButton":{},"input":{},"label":{},"successMessage":{},"checkbox":{},"radio":{},"pageNavigation":{}}},{"type":"null"}]},"pages":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"fieldIds":{"type":"array","items":{"type":"string"}},"belowButtonFieldIds":{"type":"array","items":{"type":"string"}},"navigation":{}},"required":["id","title","fieldIds"]},"maxItems":50},"isMultiStep":{"type":"boolean"},"steps":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"title":{"type":"string"},"description":{"type":"string"},"fieldIds":{"type":"array","items":{"type":"string"}}},"required":["title","fieldIds"]},"maxItems":50}},"minProperties":1}
    FormDelete: {"type":"object","additionalProperties":false,"properties":{"confirmSignedSubmissionCount":{"type":"integer","minimum":0,"maximum":9007199254740991}}}
    FormFolderCreate: {"type":"object","additionalProperties":false,"properties":{"name":{"type":"string"},"parentId":{"type":"string","description":"formFolders identifier."}},"required":["name"]}
    FormFolderUpdate: {"type":"object","additionalProperties":false,"properties":{"name":{"type":"string"}},"required":["name"]}
    FormDefinition: {"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"enum":["draft","published","archived"]},"schema":{"type":"array","items":{"$ref":"#/components/schemas/FormField"}},"settings":{"type":"object","additionalProperties":false,"properties":{"compliance":{"type":"object","additionalProperties":false,"properties":{"enabled":{"type":"boolean"},"companyName":{"type":"string"},"companyWebsite":{"type":"string"},"privacyPolicyUrl":{"type":"string"},"termsUrl":{"type":"string"},"footerHtml":{"type":"string"},"smsConsentText":{"type":"string"},"marketingConsentText":{"type":"string"}}},"successElements":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"enum":["heading","textContent","html","image","divider"]},"label":{"type":"string"},"defaultValue":{"anyOf":[{"type":"string"},{"type":"null"}]},"placeholder":{"anyOf":[{"type":"string"},{"type":"null"}]},"required":{"type":"boolean"},"imageUrl":{"type":"string"},"imageAlt":{"type":"string"},"width":{"type":"string"},"styleOverrides":{}},"required":["id","type"]}},"redirectUrl":{"type":"string"},"successMessage":{"type":"string"},"thankYouMessage":{"type":"string"},"submitButtonText":{"type":"string"},"embedType":{"enum":["inline","popup","sticky_sidebar","slide_in"]},"trackViews":{"type":"boolean"},"showPoweredBy":{"type":"boolean"},"allowUrlPrefill":{"type":"boolean"},"retentionDays":{"type":"number"}}},"theme":{"anyOf":[{"$ref":"#/components/schemas/FormTheme"},{"type":"null"}]},"isMultiStep":{"type":"boolean"},"steps":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"title":{"type":"string"},"description":{"type":"string"},"fieldIds":{"type":"array","items":{"type":"string"}}},"required":["title","fieldIds"]}},"pages":{"type":"array","items":{"$ref":"#/components/schemas/FormPage"}},"folderId":{"type":["string","null"]},"isPreferenceCenter":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","name","description","status","schema","settings","theme","isMultiStep","steps","pages","folderId","isPreferenceCenter","createdAt","updatedAt"]}
    FormSubmission: {"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"formId":{"type":"string"},"contactId":{"type":["string","null"]},"answers":{"type":"object","additionalProperties":{"anyOf":[{"type":["string","number","boolean","null"]},{"type":"array","items":{"type":["string","number","boolean","null"]}},{"type":"object","additionalProperties":{"type":["string","number","boolean","null"]}}]}},"attachments":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"fieldId":{"type":"string"},"kind":{"enum":["file","signature","signed-copy"]}},"required":["fieldId","kind"]}},"submittedAt":{"type":"string","format":"date-time"},"completionMs":{"type":["number","null"]},"status":{"enum":["quarantined","released"]}},"required":["id","formId","contactId","answers","attachments","submittedAt","completionMs","status"]}
    FormFolder: {"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"name":{"type":"string"},"parentId":{"type":["string","null"]},"sortOrder":{"type":"number"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","name","parentId","sortOrder","createdAt","updatedAt"]}
    FormAnalytics: {"type":"object","additionalProperties":false,"properties":{"viewCount":{"type":"number"},"submissionCount":{"type":"number"},"completionRate":{"type":"number"},"submissionsOverTime":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"date":{"type":"string"},"submissions":{"type":"number"}},"required":["date","submissions"]}},"avgCompletionMs":{"type":["number","null"]},"submissionsOverTimePartial":{"type":"boolean"}},"required":["viewCount","submissionCount","completionRate","submissionsOverTime","avgCompletionMs","submissionsOverTimePartial"]}
    IntegrationCompanyNote: {"type":"object","additionalProperties":false,"required":["id","companyId","content","isPinned","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"companyId":{"type":"string"},"content":{"type":"string"},"isPinned":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}
    IntegrationDirectoryUser: {"type":"object","additionalProperties":false,"required":["id","firstName","lastName","displayName"],"properties":{"id":{"type":"string"},"firstName":{"type":["string","null"]},"lastName":{"type":["string","null"]},"displayName":{"type":["string","null"]}}}
    IntegrationDirectoryTeam: {"type":"object","additionalProperties":false,"required":["id","name","description"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]}}}
    IntegrationEmailLayoutSummary: {"type": "object", "additionalProperties": false, "properties": {"id": {"type": "string"}, "name": {"type": "string"}, "templateType": {"type": "string", "enum": ["layout"]}, "subject": {"type": ["string", "null"]}, "preheader": {"type": ["string", "null"]}, "createdAt": {"type": "string", "format": "date-time"}, "updatedAt": {"type": "string", "format": "date-time"}}, "required": ["id", "name", "templateType", "subject", "preheader", "createdAt", "updatedAt"]}
    IntegrationEmailLayout: {"type": "object", "additionalProperties": false, "properties": {"id": {"type": "string"}, "name": {"type": "string"}, "templateType": {"type": "string", "enum": ["layout"]}, "subject": {"type": ["string", "null"]}, "preheader": {"type": ["string", "null"]}, "createdAt": {"type": "string", "format": "date-time"}, "updatedAt": {"type": "string", "format": "date-time"}, "bodyHtml": {"type": "string"}}, "required": ["id", "name", "templateType", "subject", "preheader", "createdAt", "updatedAt", "bodyHtml"]}
    IntegrationCustomValue: {"type": "object", "additionalProperties": false, "properties": {"id": {"type": "string"}, "key": {"type": "string"}, "value": {"type": "string"}, "description": {"type": ["string", "null"]}, "createdAt": {"type": "string", "format": "date-time"}, "updatedAt": {"type": "string", "format": "date-time"}}, "required": ["id", "key", "value", "description", "createdAt", "updatedAt"]}
    IntegrationContactFieldValues: {"type": "object", "additionalProperties": false, "properties": {"contactId": {"type": "string"}, "values": {"type": "object", "additionalProperties": {"type": ["string", "number", "boolean", "null"]}}}, "required": ["contactId", "values"]}
    IntegrationContactCompany: {"type": "object", "additionalProperties": false, "properties": {"contactId": {"type": "string"}, "companyId": {"type": ["string", "null"]}}, "required": ["contactId", "companyId"]}
    IntegrationCompanyContact: {"type": "object", "additionalProperties": false, "properties": {"contactId": {"type": "string"}}, "required": ["contactId"]}
    IntegrationValueWriteReceipt: {"type": "object", "additionalProperties": false, "properties": {"id": {"type": "string"}, "created": {"type": "boolean"}, "updated": {"type": "boolean"}}, "required": ["id"]}
    IntegrationTag: {"type": "object", "additionalProperties": false, "required": ["id", "name", "color", "description", "createdAt", "updatedAt"], "properties": {"id": {"type": "string"}, "name": {"type": "string"}, "color": {"type": ["string", "null"]}, "description": {"type": ["string", "null"]}, "createdAt": {"type": "string", "format": "date-time"}, "updatedAt": {"type": "string", "format": "date-time"}}}
    IntegrationContactField: {"type": "object", "additionalProperties": false, "required": ["id", "object", "name", "label", "fieldType", "options", "isRequired", "sortOrder", "createdAt", "updatedAt"], "properties": {"id": {"type": "string"}, "object": {"type": "string", "enum": ["contact"]}, "name": {"type": "string"}, "label": {"type": "string"}, "fieldType": {"type": "string", "enum": ["text", "number", "date", "select", "boolean", "url", "email", "phone", "monetary", "file", "signature", "radio", "textbox_list"]}, "options": {"type": "array", "items": {"type": "string"}}, "isRequired": {"type": "boolean"}, "sortOrder": {"type": "number"}, "createdAt": {"type": "string", "format": "date-time"}, "updatedAt": {"type": "string", "format": "date-time"}}}
    IntegrationContactList: {"type": "object", "additionalProperties": false, "required": ["id", "name", "description", "membershipMode", "isTransactional", "createdAt", "updatedAt"], "properties": {"id": {"type": "string"}, "name": {"type": "string"}, "description": {"type": ["string", "null"]}, "membershipMode": {"type": "string", "enum": ["manual"]}, "isTransactional": {"type": "boolean"}, "createdAt": {"type": "string", "format": "date-time"}, "updatedAt": {"type": "string", "format": "date-time"}}}
    IntegrationListMember: {"type": "object", "additionalProperties": false, "required": ["contactId"], "properties": {"contactId": {"type": "string"}}}
    IntegrationListMembershipReceipt: {"type": "object", "additionalProperties": false, "required": ["id", "contactId", "updated"], "properties": {"id": {"type": "string"}, "contactId": {"type": "string"}, "updated": {"type": "boolean", "enum": [true]}}}
    IntegrationCreatedId: {"type": "object", "additionalProperties": false, "required": ["id"], "properties": {"id": {"type": "string"}}}
    IntegrationCreatedReceipt: {"type": "object", "additionalProperties": false, "required": ["id", "created"], "properties": {"id": {"type": "string"}, "created": {"type": "boolean", "enum": [true]}}}
    IntegrationUpdatedReceipt: {"type": "object", "additionalProperties": false, "required": ["id", "updated"], "properties": {"id": {"type": "string"}, "updated": {"type": "boolean", "enum": [true]}}}
    ProfileReadPage:
      type: object
      required: [limit, hasMore, cursor]
      properties:
        limit: { type: integer }
        hasMore: { type: boolean }
        cursor: { type: string, nullable: true }
    CompanyProfile:
      type: object
      additionalProperties: false
      required: [id, name, domain, phone, email, website, industry, size, addressLine1, addressLine2, city, state, postalCode, country, createdAt, updatedAt]
      properties:
        id: { type: string }
        name: { type: string }
        domain: { type: string, nullable: true }
        phone: { type: string, nullable: true }
        email: { type: string, nullable: true }
        website: { type: string, nullable: true }
        industry: { type: string, nullable: true }
        size: { type: string, nullable: true }
        addressLine1: { type: string, nullable: true }
        addressLine2: { type: string, nullable: true }
        city: { type: string, nullable: true }
        state: { type: string, nullable: true }
        postalCode: { type: string, nullable: true }
        country: { type: string, nullable: true }
        createdAt: { type: string, format: date-time }
        updatedAt: { type: string, format: date-time }
    ContactNoteRead:
      type: object
      additionalProperties: false
      required: [id, contactId, content, isPinned, createdAt, updatedAt]
      properties:
        id: { type: string }
        contactId: { type: string }
        content: { type: string, description: Untrusted author-entered content; may contain links or sensitive data }
        isPinned: { type: boolean }
        createdAt: { type: string, format: date-time }
        updatedAt: { type: string, format: date-time }
    OAuthWriteResponse:
      type: object
      required: [data]
      properties:
        data:
          type: object
          required: [id]
          properties:
            id: { type: string }
            updated: { type: boolean }
            created: { type: boolean }
            conversationId: { type: string }
            status: { type: string, description: Status when the write was accepted }
    ConnectedAppCallContextRequest:
      type: "object"
      additionalProperties: false
      required:
        - "ticket"
        - "externalCallId"
      properties:
        ticket:
          type: "string"
          pattern: "^seedly_cc_[a-f0-9]{64}$"
        externalCallId:
          type: "string"
          pattern: "^[A-Za-z0-9._:-]{1,128}$"
    ConnectedAppCallContextReceipt:
      type: "object"
      additionalProperties: false
      required:
        - "callLogId"
        - "contactId"
        - "direction"
        - "externalCallId"
        - "replayed"
      properties:
        callLogId:
          type: "string"
        contactId:
          type: "string"
        direction:
          type: "string"
          enum:
            - "inbound"
        externalCallId:
          type: "string"
        replayed:
          type: "boolean"
    ConnectedAppRecordingReceipt:
      type: "object"
      additionalProperties: false
      required:
        - "recordingId"
        - "callLogId"
        - "replayed"
      properties:
        recordingId:
          type: "string"
        callLogId:
          type: "string"
        replayed:
          type: "boolean"
    ConnectedAppTranscriptRequest:
      type: "object"
      additionalProperties: false
      required:
        - "callLogId"
        - "text"
      properties:
        callLogId:
          type: "string"
          minLength: 1
          maxLength: 128
        text:
          type: "string"
          minLength: 1
          maxLength: 64000
          description: "Also capped at 64,000 UTF-16 code units by runtime validation"
        language:
          type: "string"
          minLength: 1
          maxLength: 35
        model:
          type: "string"
          minLength: 1
          maxLength: 100
        segments:
          type: "array"
          minItems: 1
          maxItems: 500
          description: "Sorted by startMs; endMs must be at least startMs and no greater than call duration
            plus one second. Overlap is allowed."
          items:
            type: "object"
            additionalProperties: false
            required:
              - "speaker"
              - "startMs"
              - "endMs"
              - "text"
            properties:
              speaker:
                type: "string"
                minLength: 1
                maxLength: 80
              startMs:
                type: "integer"
                minimum: 0
                maximum: 86400000
              endMs:
                type: "integer"
                minimum: 0
                maximum: 86400000
              text:
                type: "string"
                minLength: 1
                maxLength: 4000
    ConnectedAppTranscriptReceipt:
      type: "object"
      additionalProperties: false
      required:
        - "transcriptId"
        - "callLogId"
        - "replayed"
      properties:
        transcriptId:
          type: "string"
          minLength: 1
          maxLength: 128
        callLogId:
          type: "string"
          minLength: 1
          maxLength: 128
        replayed:
          type: "boolean"
    ConnectedAppContactLookup:
      type: "object"
      additionalProperties: false
      properties:
        contactId:
          type: "string"
          minLength: 1
          maxLength: 128
        email:
          type: "string"
          format: "email"
          minLength: 1
          maxLength: 200
        phone:
          type: "string"
          minLength: 1
          maxLength: 40
          description: "Normalized to E.164; US default for national input"
        lastName:
          type: "string"
          minLength: 1
          maxLength: 200
      anyOf:
        - required:
            - "contactId"
        - required:
            - "email"
            - "phone"
        - required:
            - "email"
            - "lastName"
        - required:
            - "phone"
            - "lastName"
    ConnectedAppContactCreate:
      type: "object"
      additionalProperties: false
      properties:
        firstName:
          type: "string"
          minLength: 1
          maxLength: 200
        lastName:
          type: "string"
          minLength: 1
          maxLength: 200
        email:
          type: "string"
          format: "email"
          minLength: 1
          maxLength: 200
        phone:
          type: "string"
          minLength: 1
          maxLength: 40
          description: "Normalized to E.164; US default for national input"
        company:
          type: "string"
          maxLength: 200
      required:
        - "firstName"
        - "lastName"
      anyOf:
        - required:
            - "email"
        - required:
            - "phone"
    ConnectedAppContactUpdate:
      type: "object"
      additionalProperties: false
      properties:
        contactId:
          type: "string"
          minLength: 1
          maxLength: 128
        expectedUpdatedAt:
          type: "integer"
          minimum: 0
          maximum: 9007199254740991
          description: "Unix milliseconds"
        changes:
          type: "object"
          additionalProperties: false
          properties:
            firstName:
              type: "string"
              minLength: 1
              maxLength: 200
            lastName:
              type: "string"
              minLength: 1
              maxLength: 200
            email:
              type: "string"
              format: "email"
              minLength: 1
              maxLength: 200
            phone:
              type: "string"
              minLength: 1
              maxLength: 40
              description: "Normalized to E.164; US default for national input"
            company:
              type: "string"
              maxLength: 200
          minProperties: 1
      required:
        - "contactId"
        - "expectedUpdatedAt"
        - "changes"
    ConnectedAppCallReport:
      type: "object"
      additionalProperties: false
      properties:
        externalCallId:
          type: "string"
          pattern: "^[A-Za-z0-9._:-]{1,128}$"
        crmCallLogId:
          type: "string"
          minLength: 1
          maxLength: 128
        contactId:
          type: "string"
          minLength: 1
          maxLength: 128
        direction:
          type: "string"
          enum:
            - "inbound"
            - "outbound"
        outcome:
          type: "string"
          enum:
            - "answered"
            - "no_answer"
            - "voicemail"
            - "busy"
            - "cancelled"
            - "failed"
            - "missed"
        calledAt:
          type: "integer"
          minimum: 1
          maximum: 9007199254740991
          description: "Unix milliseconds"
        endedAt:
          type: "integer"
          minimum: 1
          maximum: 9007199254740991
          description: "Unix milliseconds"
        duration:
          type: "integer"
          minimum: 0
          maximum: 86400
          description: "Seconds, at most elapsed interval plus one second"
        callerNumber:
          type: "string"
          minLength: 1
          maxLength: 40
          description: "Normalized to E.164; US default for national input"
        calledNumber:
          type: "string"
          minLength: 1
          maxLength: 40
          description: "Normalized to E.164; US default for national input"
        summary:
          type: "string"
          maxLength: 4000
        notes:
          type: "string"
          maxLength: 4000
      required:
        - "externalCallId"
        - "contactId"
        - "direction"
        - "outcome"
        - "calledAt"
        - "endedAt"
        - "duration"
        - "callerNumber"
        - "calledNumber"
    ConnectedAppContact:
      type: "object"
      additionalProperties: false
      properties:
        contactId:
          type: "string"
          minLength: 1
          maxLength: 128
        firstName:
          type: "string"
        lastName:
          type: "string"
        email:
          type:
            - "string"
            - "null"
        phone:
          type:
            - "string"
            - "null"
        company:
          type:
            - "string"
            - "null"
        updatedAt:
          type: "integer"
          minimum: 0
          maximum: 9007199254740991
          description: "Unix milliseconds"
      required:
        - "contactId"
        - "firstName"
        - "lastName"
        - "email"
        - "phone"
        - "company"
        - "updatedAt"
    ConnectedAppContactReceipt:
      type: "object"
      additionalProperties: false
      properties:
        contactId:
          type: "string"
          minLength: 1
          maxLength: 128
        updatedAt:
          type: "integer"
          minimum: 0
          maximum: 9007199254740991
          description: "Unix milliseconds"
        replayed:
          type: "boolean"
      required:
        - "contactId"
        - "updatedAt"
        - "replayed"
    ConnectedAppCallReceipt:
      type: "object"
      additionalProperties: false
      properties:
        contactId:
          type: "string"
          minLength: 1
          maxLength: 128
        callLogId:
          type: "string"
          minLength: 1
          maxLength: 128
        replayed:
          type: "boolean"
      required:
        - "contactId"
        - "callLogId"
        - "replayed"
    OAuthBookAppointment:
      type: object
      additionalProperties: false
      required: [appointmentTypeId, startTime, endTime, firstName, lastName, email]
      properties:
        appointmentTypeId: { type: string }
        startTime: { type: number, description: Unix timestamp in milliseconds from availability }
        endTime: { type: number, description: Unix timestamp in milliseconds from availability }
        firstName: { type: string }
        lastName: { type: string }
        email: { type: string, format: email }
        phone: { type: string }
        notes: { type: string }
        confirmationMode: { type: string, enum: [automatic, requested], default: automatic }
        holdExternalCallId: { type: string, description: "Consume this app call's active appointment hold when booking" }
    OAuthBookingReceipt:
      type: object
      required:
        [
          appointmentId,
          startTime,
          endTime,
          timezone,
          status,
          confirmationMode,
          confirmation,
          replayed,
        ]
      properties:
        appointmentId: { type: string }
        startTime: { type: number }
        endTime: { type: number }
        timezone: { type: string }
        status: { type: string }
        confirmationMode: { type: string, enum: [automatic, requested] }
        confirmation: { type: string, enum: [calendar_rules, requested, not_requested] }
        replayed: { type: boolean }
    VerifiedAppointment:
      type: object
      description: |
        One appointment, as returned to a verified customer. An ALLOWLIST, not a
        redaction: the underlying row also carries notes, payment fields,
        assignee, guest emails and the booking token, and none of those appear
        here or can be added by a new column existing.
      properties:
        id: { type: string }
        title: { type: string }
        startTime: { type: integer, description: Unix ms }
        endTime: { type: integer, description: Unix ms }
        timezone: { type: string, example: America/New_York }
        localDate: { type: string, example: "2026-09-10" }
        label:
          type: string
          description: Human-readable time in the calendar's timezone. Use THIS when asking a customer to choose.
          example: "Thursday, September 10, 2026 at 1:00 PM EDT"
        status: { type: string, example: scheduled }
        canCancel:
          type: boolean
          description: Read from the same calendar settings the write path enforces, so you are never told you may cancel something the next call refuses.
        canReschedule: { type: boolean }
        partOfSeries:
          type: boolean
          description: |
            True when this belongs to a recurring booking. Both write endpoints
            WILL refuse it and notify an operator instead. Handle it before
            offering, not after being turned down.
    # -----------------------------------------------------------------------
    # Enums
    # -----------------------------------------------------------------------
    LifecycleStage:
      type: string
      enum: [lead, qualified, customer, repeat, inactive]

    Channel:
      type: string
      enum: [sms, email, messenger, instagram, gmail, live_chat, social_dm]

    ConversationStatus:
      type: string
      enum: [open, closed, snoozed]

    MessageDirection:
      type: string
      enum: [inbound, outbound]

    MessageStatus:
      type: string
      enum: [pending, sent, delivered, read, failed, bounced]

    AppointmentStatus:
      type: string
      enum: [scheduled, cancelled]

    ErrorCode:
      type: string
      enum:
        - UNAUTHORIZED
        - KEY_REVOKED
        - KEY_EXPIRED
        - FORBIDDEN
        - NOT_FOUND
        - RATE_LIMITED
        - VALIDATION_ERROR
        - INTERNAL_ERROR
        - MISSING_SUB_ACCOUNT
        - INVALID_SUB_ACCOUNT
        - DUPLICATE_OPPORTUNITY

    WebhookEventType:
      type: string
      enum:
        - contact.created
        - contact.deleted
        - contact.updated
        - contact.lifecycle_changed
        - contact.tag_added
        - message.received
        - message.sent
        - message.delivered
        - message.failed
        - appointment.booked
        - appointment.cancelled
        - appointment.rescheduled
        - appointment.confirmed
        - appointment.completed
        - appointment.no_show
        - opportunity.created
        - opportunity.stage_changed
        - opportunity.won
        - opportunity.lost
        - form.submitted
        - review.received
        - invoice.paid
        - task.contact_deleted
        - appointment.contact_deleted

    LinkedEventReferenceData:
      type: object
      description: >-
        Reference-only body sent to record-restricted grants (policy 14 allowLinkedEvents) for
        form.submitted, review.received and appointment.* events, and to location-wide OAuth grants
        that approved appointment notifications. IDs only. Fetch details with a separately
        authorized read.
      additionalProperties: false
      required: [deliveryMode, subAccountId, contactId]
      properties:
        deliveryMode: { const: "record-reference-v1" }
        subAccountId: { type: string }
        contactId: { type: string }
        formId: { type: string }
        submissionId: { type: string }
        reviewId: { type: string }
        appointmentId: { type: string }
        calendarId: { type: string }

    ContactCascadeEventData:
      type: object
      additionalProperties: false
      required: [deliveryMode, contactDeleted, subAccountId, contactId]
      properties:
        deliveryMode: { const: "record-reference-v1" }
        contactDeleted: { const: true }
        subAccountId: { type: string }
        contactId: { type: string }
        taskId: { type: string }
        appointmentId: { type: string }
        cascadeTruncated:
          const: true
          description: More children were affected than were sent. List the records instead.

    CustomFieldType:
      type: string
      enum: [text, number, date, select, boolean, url, email, phone]

    # -----------------------------------------------------------------------
    # Response envelopes
    # -----------------------------------------------------------------------
    PaginationMeta:
      type: object
      properties:
        total:
          type: integer
          description: Total matching records (when available)
        hasMore:
          type: boolean
          description: Whether more results exist beyond this page
        cursor:
          type:
            - string
            - "null"
          description: Cursor to pass for the next page (null when no more pages)
        totalIsLowerBound:
          type: boolean
          description: Standard v2 and OAuth on contacts, tasks and opportunities. True when total is a floor because the count stopped at a read bound, false when it is exact.
        truncated:
          type: boolean
          description: Standard v2 and OAuth on a bounded list with no cursor, such as contact search. True when a read cap or the limit stopped the answer before the list ended.

    ErrorResponse:
      type: object
      required: [error]
      properties:
        error:
          type: object
          required: [code, message]
          properties:
            code:
              $ref: "#/components/schemas/ErrorCode"
            message:
              type: string
            details:
              type: object
              description: |
                Additional error context, when the error has a machine-readable
                recovery path. Endpoint-specific: only the keys documented for
                that endpoint's error appear, and `details` is absent otherwise.
              additionalProperties: true
              properties:
                field:
                  type: string
                  description: The request field the error is about, when the error names one
                matches:
                  type: array
                  description: |
                    Candidate rows when a lookup was ambiguous. Returned by
                    `GET /api/v1/calendars/availability` when `appointmentType`
                    names more than one bookable appointment type: retry with
                    one of these `id` values as `appointmentTypeId`.
                  items:
                    $ref: "#/components/schemas/AppointmentTypeMatch"

    AppointmentTypeMatch:
      type: object
      description: One candidate from an ambiguous appointment-type lookup.
      required: [id, name, slug, calendarId]
      properties:
        id:
          type: string
          description: Pass this back as `appointmentTypeId` to disambiguate
        name:
          type: string
        slug:
          type: string
        calendarId:
          type: string

    # -----------------------------------------------------------------------
    # Contact schemas
    # -----------------------------------------------------------------------
    MessagingVerdict:
      type: object
      required: [allowed, reason]
      properties:
        allowed:
          type: boolean
        reason:
          type: string
          description: "`allowed`, or the first check that blocks the send."
          enum:
            - allowed
            - no_phone
            - no_email
            - dnd
            - sms_opted_out
            - suppressed
            - unsubscribed
            - marketing_sms_consent_required
            - marketing_sms_consent_declined

    ContactMessagingStatus:
      type: object
      required: [contactId, sms, email]
      properties:
        contactId:
          type: string
        sms:
          type: object
          required: [transactional, marketing]
          properties:
            transactional:
              $ref: "#/components/schemas/MessagingVerdict"
            marketing:
              $ref: "#/components/schemas/MessagingVerdict"
        email:
          type: object
          required: [transactional, marketing]
          properties:
            transactional:
              $ref: "#/components/schemas/MessagingVerdict"
            marketing:
              $ref: "#/components/schemas/MessagingVerdict"

    Contact:
      type: object
      required:
        - id
        - agencyId
        - subAccountId
        - firstName
        - lastName
        - isActive
        - createdAt
        - updatedAt
      properties:
        id:
          type: string
        agencyId:
          type: string
        subAccountId:
          type: string
        firstName:
          type: string
        lastName:
          type: string
        email:
          type:
            - string
            - "null"
        phone:
          type:
            - string
            - "null"
        company:
          type:
            - string
            - "null"
        companyId:
          type:
            - string
            - "null"
        title:
          type:
            - string
            - "null"
        source:
          type:
            - string
            - "null"
          description: "Read-only. Defaults to `api` for API-created contacts."
        lifecycleStage:
          type:
            - string
            - "null"
          enum: [lead, qualified, customer, repeat, inactive, null]
        sourceFormId:
          type:
            - string
            - "null"
        sourceCampaignId:
          type:
            - string
            - "null"
        tags:
          type: array
          items:
            type: string
        customFields:
          type: object
          additionalProperties: true
          description: Key-value pairs for custom field values
        avatarUrl:
          type:
            - string
            - "null"
        additionalEmails:
          type: array
          items:
            type: string
        additionalPhones:
          type: array
          items:
            type: string
        addressLine1:
          type:
            - string
            - "null"
        addressLine2:
          type:
            - string
            - "null"
        city:
          type:
            - string
            - "null"
        state:
          type:
            - string
            - "null"
        postalCode:
          type:
            - string
            - "null"
        country:
          type:
            - string
            - "null"
        dndSettings:
          type:
            - object
            - "null"
          description: Do-not-disturb settings per channel
        emailConsent:
          type:
            - string
            - "null"
          enum: [opted_in, opted_out, not_set, null]
          description: Email marketing consent status
        smsConsent:
          oneOf:
            - $ref: "#/components/schemas/SmsConsent"
            - type: "null"
          description: Structured SMS consent object, or null if not set
        smsMarketingConsent:
          type:
            - object
            - "null"
          description: >-
            Marketing-purpose SMS consent, separate from smsConsent (which only
            records reachability). Null when never recorded.
          properties:
            status:
              type: string
              enum: [granted, declined, revoked]
            at:
              type: string
              format: date-time
              description: When the marketing consent last changed
            method:
              type: string
            source:
              type: string
        emailConsentAt:
          type:
            - string
            - "null"
          format: date-time
          description: Timestamp of last email consent change
        smsConsentAt:
          type:
            - string
            - "null"
          format: date-time
          description: Timestamp of last SMS consent change
        consentSource:
          type:
            - string
            - "null"
          enum: [form, import, manual, api, null]
          description: Origin of the most recent consent action
        engagementScore:
          type:
            - integer
            - "null"
          minimum: 0
          maximum: 100
          description: "Read-only. Calculated engagement score."
        isActive:
          type: boolean
        assignedTo:
          type:
            - string
            - "null"
          description: Assigned user ID
        dateOfBirth:
          type:
            - string
            - "null"
        timezone:
          type:
            - string
            - "null"
          description: IANA timezone (e.g. `America/New_York`)
        deletedAt:
          type:
            - string
            - "null"
          format: date-time
        lastContactedAt:
          type:
            - string
            - "null"
          format: date-time
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time

    SmsConsent:
      type: object
      required: [status]
      properties:
        status:
          type: string
          enum: [granted, revoked, unknown]
          description: Current SMS consent status
        method:
          type:
            - string
            - "null"
          description: How consent was collected (e.g., "keyword", "form")
        grantedAt:
          type:
            - string
            - "null"
          format: date-time
          description: Timestamp when consent was granted
        revokedAt:
          type:
            - string
            - "null"
          format: date-time
          description: Timestamp when consent was revoked
        source:
          type:
            - string
            - "null"
          description: Origin of the consent action

    ContactCreate:
      type: object
      required: [firstName, lastName]
      properties:
        firstName:
          type: string
        lastName:
          type: string
        email:
          type: string
          format: email
        phone:
          type: string
        company:
          type: string
        lifecycleStage:
          $ref: "#/components/schemas/LifecycleStage"
        tags:
          type: array
          items:
            type: string
        assignedTo:
          type: string
        addressLine1:
          type: string
        addressLine2:
          type: string
        city:
          type: string
        state:
          type: string
        postalCode:
          type: string
        country:
          type: string
        dateOfBirth:
          type: string
        timezone:
          type: string
          description: IANA timezone (e.g. `America/New_York`)
        customFields:
          type: object
          additionalProperties: true
          description: |
            Custom field values, keyed by field name.

            Reserved keys (system identifiers set by the CRM's own integrations,
            matched case-insensitively): `metaSenderId`, `messengerPsid`,
            `instagramIgsid`, `socialDmExternalId`, `socialPlatform`,
            `socialUsername`, `communityMemberId`, `externalId`, `ghlContactId`,
            `ghlOptOutsApplied`. Setting one, or changing its stored value, is
            refused with `400 VALIDATION_ERROR` (`error.field: customFields`) and
            nothing is written. Sending the value the contact already holds is
            accepted.

    ContactUpdate:
      type: object
      properties:
        firstName:
          type: string
        lastName:
          type: string
        email:
          type: string
          format: email
        phone:
          type: string
        company:
          type: string
        lifecycleStage:
          $ref: "#/components/schemas/LifecycleStage"
        tags:
          type: array
          items:
            type: string
        assignedTo:
          type:
            - string
            - "null"
        addressLine1:
          type:
            - string
            - "null"
        addressLine2:
          type:
            - string
            - "null"
        city:
          type:
            - string
            - "null"
        state:
          type:
            - string
            - "null"
        postalCode:
          type:
            - string
            - "null"
        country:
          type:
            - string
            - "null"
        dateOfBirth:
          type:
            - string
            - "null"
        timezone:
          type:
            - string
            - "null"
          description: >-
            IANA timezone (e.g. `America/New_York`). Any string is accepted for
            backward compatibility, but only a real IANA zone is honored by
            send-time scheduling; the sub-account timezone is used otherwise.
            Send `""` to clear.
        customFields:
          type: object
          additionalProperties: true
          description: |
            Custom field values, keyed by field name.

            Reserved keys (system identifiers set by the CRM's own integrations,
            matched case-insensitively): `metaSenderId`, `messengerPsid`,
            `instagramIgsid`, `socialDmExternalId`, `socialPlatform`,
            `socialUsername`, `communityMemberId`, `externalId`, `ghlContactId`,
            `ghlOptOutsApplied`. Setting one, or changing its stored value, is
            refused with `400 VALIDATION_ERROR` (`error.field: customFields`) and
            nothing is written. Sending the value the contact already holds is
            accepted.

    CustomFieldDefinition:
      type: object
      required: [id, name, label, fieldType, isRequired, sortOrder]
      properties:
        id:
          type: string
        agencyId:
          type: string
        subAccountId:
          type: string
        name:
          type: string
          description: Machine-readable field key
        label:
          type: string
          description: Human-readable display label
        fieldType:
          $ref: "#/components/schemas/CustomFieldType"
        options:
          type:
            - array
            - "null"
          items:
            type: string
          description: Available options (for `select` field type)
        isRequired:
          type: boolean
        sortOrder:
          type: integer

    # -----------------------------------------------------------------------
    # Conversation schemas
    # -----------------------------------------------------------------------
    ContactSummary:
      type: object
      description: Lightweight contact info embedded in conversation responses
      properties:
        id:
          type: string
        firstName:
          type:
            - string
            - "null"
        lastName:
          type:
            - string
            - "null"
        email:
          type:
            - string
            - "null"
        phone:
          type:
            - string
            - "null"
        company:
          type:
            - string
            - "null"
          description: Only included in single conversation responses

    Conversation:
      type: object
      required:
        - id
        - contactId
        - channel
        - status
        - unreadCount
        - createdAt
      properties:
        id:
          type: string
        contactId:
          type: string
        channel:
          $ref: "#/components/schemas/Channel"
        status:
          $ref: "#/components/schemas/ConversationStatus"
        assignedTo:
          type:
            - string
            - "null"
        subject:
          type:
            - string
            - "null"
        unreadCount:
          type: integer
        isArchived:
          type: boolean
        isStarred:
          type: boolean
        lastMessageAt:
          type:
            - string
            - "null"
          format: date-time
        createdAt:
          type: string
          format: date-time
        contact:
          type:
            - object
            - "null"
          $ref: "#/components/schemas/ContactSummary"

    ConversationWithCreatedFlag:
      description: Conversation response from create endpoint, includes `created` flag
      allOf:
        - $ref: "#/components/schemas/Conversation"
        - type: object
          required: [created]
          properties:
            created:
              type: boolean
              description: "`true` if a new conversation was created, `false` if an existing one was returned"

    ConversationCreate:
      type: object
      required: [contactId, channel]
      properties:
        contactId:
          type: string
          description: Contact ID to create the conversation for
        channel:
          $ref: "#/components/schemas/Channel"
        subject:
          type: string
          description: Subject line (for email conversations)

    ConversationUpdate:
      type: object
      properties:
        status:
          $ref: "#/components/schemas/ConversationStatus"
        assignedTo:
          type:
            - string
            - "null"
          description: User ID to assign, or null to unassign

    Message:
      type: object
      required:
        - id
        - conversationId
        - direction
        - channel
        - status
        - createdAt
      properties:
        privateChannel:
          type: boolean
          description: >-
            Present and true when the message is a Gmail message from a mailbox
            the API key's creator does not own (Gmail is a private channel). Its
            body, subject, addresses and attachments are omitted.
        id:
          type: string
        conversationId:
          type: string
        direction:
          $ref: "#/components/schemas/MessageDirection"
        channel:
          $ref: "#/components/schemas/Channel"
        bodyText:
          type:
            - string
            - "null"
        bodyHtml:
          type:
            - string
            - "null"
        status:
          $ref: "#/components/schemas/MessageStatus"
        fromAddress:
          type:
            - string
            - "null"
          description: Sender phone number or email
        toAddress:
          type:
            - string
            - "null"
          description: Recipient phone number or email
        isInternal:
          type: boolean
        sentAt:
          type:
            - string
            - "null"
          format: date-time
        deliveredAt:
          type:
            - string
            - "null"
          format: date-time
        createdAt:
          type: string
          format: date-time

    SendMessage:
      type: object
      # channel became optional in 5.8.0 (additive relaxation): absent, empty,
      # or an unsubstituted "{{...}}" template value falls back to the target
      # conversation's own channel.
      required: [bodyText]
      properties:
        bodyText:
          type: string
          description: Plain text message body
        bodyHtml:
          type: string
          description: HTML message body (for email)
        channel:
          $ref: "#/components/schemas/Channel"
        toAddress:
          type: string
          description: Recipient email or phone. Optional - falls back to the contact's phone (sms) or email (email channels) when omitted.
        subject:
          type: string
          description: Email subject line
        fromAddress:
          type: string
          description: >-
            Optional, `gmail` channel only: which of the API key creator's own
            connected Gmail accounts in this sub-account to send FROM (Gmail is a
            personal channel; a key sends only as the person who created it).
            When omitted, the creator's single connected Gmail account is used.
            The request returns 400 `VALIDATION_ERROR` (field `fromAddress`) when
            the creator has no Gmail connected here, has several and none is
            named, or the named address is not one of theirs. Ignored on other
            channels.
        messageType:
          type: string
          enum: [marketing, transactional]
          description: |
            Email only, optional. `transactional` (confirmations, receipts,
            replies the contact is owed) is delivered even after a marketing
            unsubscribe; bounces, spam complaints and Do Not Disturb still
            block it. `marketing` gets the full consent check plus an
            unsubscribe link and List-Unsubscribe headers.

            IMPORTANT, DEFAULT CHANGED: when `messageType` is omitted, an
            email that is NOT a reply on a conversation the contact wrote to
            in the last 30 days is sent as MARKETING: it is not delivered to
            anyone who unsubscribed from marketing email, and it carries an
            unsubscribe footer. Send `messageType: transactional` for
            receipts, confirmations and other mail the contact must get.
        listId:
          type: string
          description: |
            Email only, optional. The mailing list a marketing email is sent
            under (its opt-outs apply and its unsubscribe link is used).
            Implies `messageType: marketing` when `messageType` is omitted.
            Defaults to the sub-account's Marketing list. Must be a list in
            the same sub-account, or the request is rejected with 400.

    # -----------------------------------------------------------------------
    # Calendar schemas
    # -----------------------------------------------------------------------
    Calendar:
      type: object
      required: [id, name, timezone, isActive, createdAt, updatedAt]
      properties:
        id:
          type: string
        name:
          type: string
        slug:
          type: string
        timezone:
          type: string
          description: IANA timezone (e.g. `America/New_York`)
        type:
          type: string
          description: Calendar type (e.g. `personal`, `team`)
        isActive:
          type: boolean
        description:
          type:
            - string
            - "null"
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time

    AppointmentType:
      type: object
      required: [id, calendarId, name, duration, isActive, createdAt, updatedAt]
      properties:
        id:
          type: string
        calendarId:
          type: string
        name:
          type: string
        slug:
          type: string
        description:
          type:
            - string
            - "null"
        duration:
          type: integer
          description: Duration in minutes
        color:
          type: string
        isActive:
          type: boolean
        maxSeats:
          type:
            - integer
            - "null"
          description: Maximum seats for group appointments
        showAvailableSeats:
          type: boolean
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time

    AvailabilitySlot:
      type: object
      required:
        [
          start,
          end,
          startTime,
          endTime,
          date,
          label,
          timezone,
          customerLabel,
          customerTimezone,
          available,
        ]
      properties:
        start:
          type: string
          format: date-time
          description: Slot start as an ISO 8601 instant (UTC)
        end:
          type: string
          format: date-time
          description: Slot end as an ISO 8601 instant (UTC)
        startTime:
          type: integer
          description: |
            Slot start as a Unix timestamp (milliseconds). This is the value
            `POST /api/v1/calendars/appointments` expects.
        endTime:
          type: integer
          description: Slot end as a Unix timestamp (milliseconds)
        date:
          type: string
          format: date
          description: The slot's calendar date IN `timezone`, which is not always the UTC date
        label:
          type: string
          description: |
            The slot written out in `timezone`, ready to read to a customer,
            e.g. `Wednesday, April 1, 2026 at 9:00 AM EDT`.
          example: "Wednesday, April 1, 2026 at 9:00 AM EDT"
        timezone:
          type: string
          description: IANA timezone of the calendar this slot belongs to
          example: "America/New_York"
        customerLabel:
          type: string
          nullable: true
          description: |
            The same instant written out in `customerTimezone`, when that query
            parameter was supplied; `null` otherwise. Read this one to a
            customer in another timezone rather than converting `label`
            yourself.
          example: "Wednesday, April 1, 2026 at 6:00 AM PDT"
        customerTimezone:
          type: string
          nullable: true
          description: |
            The IANA timezone `customerLabel` was rendered in, echoing the query
            parameter; `null` when none was supplied.
          example: "America/Los_Angeles"
        available:
          type: boolean
          description: |
            Always `true`. Unavailable times are omitted from the response
            rather than listed with `available: false`.
          enum: [true]
        seatsRemaining:
          type: integer
          description: Seats left, on class calendars that show seat counts

    AvailabilityMeta:
      type: object
      required:
        [
          timezone,
          appointmentTypeId,
          appointmentTypeName,
          appointmentTypeSlug,
          startDate,
          endDate,
          days,
          daysReturned,
          truncated,
          returnsOnlyAvailableSlots,
        ]
      properties:
        timezone:
          type:
            - string
            - "null"
          description: IANA timezone of the calendar, or null when nothing matched
        appointmentTypeId:
          type:
            - string
            - "null"
          description: |
            `null` means NOTHING WAS RESOLVED - the appointment type is unknown,
            inactive, on an archived calendar, in another sub-account, or the
            sub-account itself is deactivated. Read this before treating an
            empty `data` as "nothing is free": the two answers are otherwise
            identical, and telling a customer the business is booked solid when
            the id simply was not yours is the wrong turn to take.
        appointmentTypeName:
          type:
            - string
            - "null"
        appointmentTypeSlug:
          type:
            - string
            - "null"
        startDate:
          type: string
          format: date
          description: Echo of the requested `date`
        endDate:
          type: string
          format: date
          description: Echo of the requested `endDate`; same as startDate when none was sent
        days:
          type: integer
          description: Number of days REQUESTED, inclusive
        daysReturned:
          type: integer
          description: |
            Number of days actually computed, counting from `startDate`. Equal
            to `days` unless `truncated` is `true`. Days beyond it are absent
            from `data`, which is not the same as having no free times.
        truncated:
          type: boolean
          description: |
            The range produced more bookable slots than one response carries, so
            it was cut off after `daysReturned` whole days (never mid-day). Ask
            again starting the day after.
        returnsOnlyAvailableSlots:
          type: boolean
          description: |
            Always `true`. Every slot in `data` is bookable; unavailable times
            are omitted rather than flagged. This says what the list CONTAINS,
            not why it is empty - `appointmentTypeId` says that.
          enum: [true]

    Appointment:
      type: object
      required: [id, calendarId, startTime, endTime, status, createdAt]
      properties:
        id:
          type: string
        calendarId:
          type: string
        appointmentTypeId:
          type:
            - string
            - "null"
        contactId:
          type:
            - string
            - "null"
        title:
          type:
            - string
            - "null"
        startTime:
          type: string
          format: date-time
        endTime:
          type: string
          format: date-time
        status:
          $ref: "#/components/schemas/AppointmentStatus"
        assignedTo:
          type:
            - string
            - "null"
        notes:
          type:
            - string
            - "null"
        createdAt:
          type: string
          format: date-time
        contact:
          type:
            - object
            - "null"
          $ref: "#/components/schemas/ContactSummary"

    BookAppointment:
      type: object
      required: [appointmentTypeId, startTime, endTime, firstName, lastName, email]
      properties:
        holdExternalCallId:
          type: string
          description: "Standard v2 keys only. Consumes this key's active slot hold for the same externalCallId. Ignored for legacy keys."
        appointmentTypeId:
          type: string
        startTime:
          type: integer
          description: Unix timestamp (milliseconds)
        endTime:
          type: integer
          description: Unix timestamp (milliseconds)
        firstName:
          type: string
        lastName:
          type: string
        email:
          type: string
          format: email
        phone:
          type: string
        notes:
          type: string

    # -----------------------------------------------------------------------
    # Webhook schemas
    # -----------------------------------------------------------------------
    WebhookSubscription:
      type: object
      required: [id, url, events, isActive, createdAt, updatedAt]
      properties:
        id:
          type: string
        url:
          type: string
          format: uri
        events:
          type: array
          items:
            $ref: "#/components/schemas/WebhookEventType"
        isActive:
          type: boolean
        description:
          type:
            - string
            - "null"
        createdAt:
          type: integer
          description: Unix timestamp (milliseconds)
        updatedAt:
          type: integer
          description: Unix timestamp (milliseconds)

    WebhookSubscriptionWithSecret:
      description: Webhook subscription with the signing secret (only returned on create and regenerate)
      allOf:
        - $ref: "#/components/schemas/WebhookSubscription"
        - type: object
          required: [secret]
          properties:
            secret:
              type: string
              description: HMAC-SHA256 signing secret. Store securely - only shown once.

    WebhookSubscriptionCreate:
      type: object
      required: [url, events]
      properties:
        url:
          type: string
          format: uri
          description: HTTPS endpoint to receive webhook deliveries
        events:
          type: array
          minItems: 1
          items:
            $ref: "#/components/schemas/WebhookEventType"
          description: Event types to subscribe to
        description:
          type: string
          description: Human-readable description of this subscription

    WebhookSubscriptionUpdate:
      type: object
      properties:
        url:
          type: string
          format: uri
        events:
          type: array
          minItems: 1
          items:
            $ref: "#/components/schemas/WebhookEventType"
        isActive:
          type: boolean
        description:
          type: string

    # -----------------------------------------------------------------------
    # Webhook event payload schemas
    # -----------------------------------------------------------------------
    WebhookPayloadEnvelope:
      type: object
      required: [event, timestamp, data]
      properties:
        event:
          $ref: "#/components/schemas/WebhookEventType"
        timestamp:
          type: string
          format: date-time
        data:
          type: object

    ContactCreatedEventData:
      type: object
      properties:
        contactId:
          type: string
        firstName:
          type: string
        lastName:
          type: string
        email:
          type:
            - string
            - "null"
        phone:
          type:
            - string
            - "null"
        company:
          type:
            - string
            - "null"
        source:
          type:
            - string
            - "null"
        tags:
          type: array
          items:
            type: string
        lifecycleStage:
          type:
            - string
            - "null"

    ContactUpdatedEventData:
      type: object
      properties:
        contactId:
          type: string
        firstName:
          type: string
        lastName:
          type: string
        email:
          type:
            - string
            - "null"
        phone:
          type:
            - string
            - "null"
        company:
          type:
            - string
            - "null"
        lifecycleStage:
          type:
            - string
            - "null"

    ContactLifecycleChangedEventData:
      type: object
      properties:
        contactId:
          type: string
        newStage:
          type: string
        previousStage:
          type: string

    ContactTagAddedEventData:
      type: object
      properties:
        contactId:
          type: string
        tagName:
          type: string

    MessageReceivedEventData:
      type: object
      properties:
        contactId:
          type: string
        messageId:
          type: string
        conversationId:
          type: string
        channel:
          $ref: "#/components/schemas/Channel"
        bodyText:
          type: string
        fromAddress:
          type: string
        direction:
          type: string
          const: "inbound"

    MessageStatusEventData:
      description: Shared schema for message.sent, message.delivered, and message.failed events
      type: object
      properties:
        messageId:
          type: string
        conversationId:
          type: string
        channel:
          $ref: "#/components/schemas/Channel"
        status:
          type: string
          enum: [sent, delivered, failed, bounced]
        externalId:
          type: string
          description: Provider-specific message ID

    AppointmentBookedEventData:
      type: object
      properties:
        contactId:
          type: string
        appointmentId:
          type: string
        calendarId:
          type: string
        appointmentTypeId:
          type: string
        appointmentTitle:
          type: string
        startTime:
          type: integer
          description: Unix timestamp (milliseconds)
        endTime:
          type: integer
          description: Unix timestamp (milliseconds)
        status:
          type: string
          const: "scheduled"

    OpportunityCreatedEventData:
      type: object
      properties:
        contactId:
          type: string
        opportunityId:
          type: string
        pipelineId:
          type: string
        stageId:
          type: string
        title:
          type: string
        value:
          type: number

    OpportunityStageChangedEventData:
      type: object
      properties:
        contactId:
          type: string
        opportunityId:
          type: string
        pipelineId:
          type: string
        fromStageId:
          type: string
        toStageId:
          type: string
        title:
          type: string

    OpportunityWonEventData:
      type: object
      properties:
        contactId:
          type: string
        opportunityId:
          type: string
        pipelineId:
          type: string
        title:
          type: string
        value:
          type: number

    OpportunityLostEventData:
      type: object
      properties:
        contactId:
          type: string
        opportunityId:
          type: string
        pipelineId:
          type: string
        title:
          type: string
        value:
          type: number
        lostReason:
          type:
            - string
            - "null"

    FormSubmittedEventData:
      type: object
      properties:
        contactId:
          type: string
        formId:
          type: string
        submissionId:
          type: string
        formName:
          type: string
        fields:
          type: object
          additionalProperties: true

    InvoicePaidEventData:
      type: object
      properties:
        contactId:
          type: string
        invoiceId:
          type: string
        amount:
          type: number
        currency:
          type: string
        paidAt:
          type: string
          format: date-time

    TaskEventData:
      type: object
      required: [taskId, title, status, priority]
      properties:
        taskId: { type: string }
        title: { type: string }
        status: { type: string, enum: [todo, in_review, completed, cancelled] }
        priority: { type: string, enum: [low, medium, high, urgent] }
        dueDate: { type: integer, format: int64 }
        assignedTo: { type: string }
        contactId: { type: string }
        dealId: { type: string }
        completedAt: { type: integer, format: int64, description: "task.completed only" }
        changedFields:
          type: array
          items: { type: string }
          description: "task.updated only - names of fields that changed"

    OpportunityEventData:
      type: object
      required: [opportunityId]
      properties:
        opportunityId: { type: string }
        dealId:
          type: string
          description: "Legacy alias for opportunityId - kept for backward compatibility"
        name: { type: string }
        status: { type: string, enum: [open, won, lost, abandoned] }
        value: { type: number }
        pipelineId: { type: string }
        stageId: { type: string }
        contactId: { type: string }
        assignedTo: { type: string }
        changedFields:
          type: array
          items: { type: string }
          description: "opportunity.updated only - names of fields that changed"
        closedAt: { type: integer, format: int64, description: "opportunity.won / opportunity.lost only" }
        lostReason: { type: string, description: "opportunity.lost only" }

    # -----------------------------------------------------------------------
    # Sub-Account (agency-scoped key discovery)
    # -----------------------------------------------------------------------
    ExtensionRoute:
      type: object
      description: One route contributed by an installed add-on.
      required: [namespace, method, path, scope, granted, summary]
      properties:
        namespace:
          type: string
          description: The add-on that contributed this route.
          example: "dispatch"
        method:
          type: string
          enum: [GET, POST]
        path:
          type: string
          description: The full path to call.
          example: "/api/v1/ext/dispatch/availability"
        scope:
          type: string
          description: |
            The scope an API key must carry to call it. Contributed scopes appear
            on the create-key form in the CRM alongside the built-in ones.
          example: "dispatch:read"
        granted:
          type: boolean
          description: Whether the key used for this request holds that scope.
        summary:
          type: string
          description: What the endpoint does, in one line, from the add-on.
          example: "Rank technician slots by marginal drive time"

    SubAccount:
      type: object
      required: [id, name, slug, type]
      properties:
        id:
          type: string
        name:
          type: string
        slug:
          type: string
        type:
          type: string
        businessEmail:
          type:
            - string
            - "null"
        industry:
          type:
            - string
            - "null"

    TaskRecurrence:
      type: object
      required: [frequency, interval]
      properties:
        frequency:
          type: string
          enum: [hourly, daily, weekly, monthly, yearly]
        interval:
          type: integer
          minimum: 1
          maximum: 365
        nextDueAt:
          type:
            - integer
            - "null"
          format: int64
        endCondition:
          type:
            - object
            - "null"
          properties:
            type:
              type: string
              enum: [never, on_date, after_count]
            endDate:
              type:
                - integer
                - "null"
              format: int64
            maxOccurrences:
              type:
                - integer
                - "null"
        occurrenceCount:
          type:
            - integer
            - "null"
        createEvenIfOverdue:
          type:
            - boolean
            - "null"

    Task:
      type: object
      required: [id, agencyId, subAccountId, title, status, priority, createdBy, createdAt, updatedAt]
      properties:
        id: { type: string }
        agencyId: { type: string }
        subAccountId: { type: string }
        title: { type: string, maxLength: 500 }
        description:
          type:
            - string
            - "null"
        status:
          type: string
          enum: [todo, in_review, completed, cancelled]
          description: >-
            On write, the legacy value `in_progress` is still accepted and
            normalises to `todo`. `cancelled` is a real terminal status: it is
            stored as-is and never stamps completedAt.
        priority:
          type: string
          enum: [low, medium, high, urgent]
        dueDate:
          type:
            - integer
            - "null"
          format: int64
          description: Epoch milliseconds
        completedAt:
          type:
            - integer
            - "null"
          format: int64
        reminderAt:
          type:
            - integer
            - "null"
          format: int64
          description: >-
            Reserved. Always returned as null: pmTasks has no reminderAt column.
            Accepted on write for forward compatibility but not persisted.
        assignedTo:
          type:
            - string
            - "null"
        contactId:
          type:
            - string
            - "null"
        dealId:
          type:
            - string
            - "null"
        conversationId:
          type:
            - string
            - "null"
          description: >-
            Reserved. Always returned as null: pmTasks has no conversationId
            column.
        recurrence:
          description: >-
            Reserved. Always returned as null: pmTasks has no recurrence column.
            Recurring work lives in pmRecurringTasks.
          oneOf:
            - { $ref: "#/components/schemas/TaskRecurrence" }
            - type: "null"
        parentRecurrenceId:
          type:
            - string
            - "null"
        createdBy: { type: string, description: "User id, or empty string when the task was created via API with no user identity" }
        createdAt: { type: string, format: date-time }
        updatedAt: { type: string, format: date-time }

    TaskCreate:
      type: object
      required: [title]
      properties:
        title: { type: string, minLength: 1, maxLength: 500 }
        description: { type: string }
        status: { type: string, enum: [todo, in_review, completed, cancelled] }
        priority: { type: string, enum: [low, medium, high, urgent] }
        dueDate: { type: integer, format: int64 }
        reminderAt: { type: integer, format: int64 }
        assignedTo: { type: string }
        contactId: { type: string }
        dealId: { type: string }
        recurrence:
          allOf:
            - $ref: "#/components/schemas/TaskRecurrence"
          description: >-
            Accepted but NOT persisted: pmTasks has no recurrence column, so the
            created task returns recurrence null and no occurrence is generated.
            Recurring work lives in pmRecurringTasks.

    TaskUpdate:
      type: object
      description: >-
        All fields optional. `recurrence` is accepted but NOT persisted: pmTasks has
        no recurrence column, and the Task response always returns it as null.
      properties:
        title: { type: string, maxLength: 500 }
        description: { type: string }
        status: { type: string, enum: [todo, in_review, completed, cancelled] }
        priority: { type: string, enum: [low, medium, high, urgent] }
        dueDate: { type: integer, format: int64 }
        reminderAt: { type: integer, format: int64 }
        assignedTo: { type: string }
        contactId: { type: string }
        dealId: { type: string }
        recurrence:
          oneOf:
            - { $ref: "#/components/schemas/TaskRecurrence" }
            - type: "null"

    # -----------------------------------------------------------------------
    # Opportunities + Pipelines
    # -----------------------------------------------------------------------
    Opportunity:
      type: object
      required:
        - id
        - agencyId
        - subAccountId
        - pipelineId
        - stageId
        - contactId
        - name
        - currency
        - tags
        - status
        - customFields
        - followers
        - createdAt
        - updatedAt
      properties:
        id: { type: string }
        agencyId: { type: string }
        subAccountId: { type: string }
        pipelineId: { type: string }
        stageId: { type: string }
        contactId: { type: string }
        name: { type: string }
        value:
          type:
            - number
            - "null"
        currency:
          type: string
          description: ISO 4217 currency code (e.g. `USD`)
        assignedTo:
          type:
            - string
            - "null"
        tags:
          type: array
          items: { type: string }
        status:
          type: string
          enum: [open, won, lost, abandoned]
        source:
          type:
            - string
            - "null"
        expectedCloseDate:
          type:
            - integer
            - "null"
          format: int64
          description: Epoch milliseconds
        lostReason:
          type:
            - string
            - "null"
        customFields:
          type: object
          additionalProperties: true
        closedAt:
          type:
            - integer
            - "null"
          format: int64
          description: Epoch milliseconds - set when status transitions to `won`, `lost`, or `abandoned`
        followers:
          type: array
          items: { type: string }
        probabilityOverride:
          type:
            - integer
            - "null"
          minimum: 0
          maximum: 100
          description: Optional per-opportunity probability override (0-100). When null, the stage's probability is used.
        score:
          type:
            - integer
            - "null"
          minimum: 0
          maximum: 100
        estimateId:
          type:
            - string
            - "null"
        invoiceId:
          type:
            - string
            - "null"
        deletedAt:
          type:
            - integer
            - "null"
          format: int64
          description: Epoch milliseconds - set on soft delete
        createdAt: { type: string, format: date-time }
        updatedAt: { type: string, format: date-time }

    OpportunityCreate:
      type: object
      required: [pipelineId, stageId, contactId, name]
      properties:
        pipelineId: { type: string }
        stageId: { type: string }
        contactId: { type: string }
        name: { type: string, minLength: 1 }
        value: { type: number }
        currency:
          type: string
          description: ISO 4217 currency code. Defaults to the sub-account's configured currency when omitted.
        assignedTo: { type: string }
        tags:
          type: array
          items: { type: string }
        customFields:
          type: object
          additionalProperties: true
          description: |
            Replaces the opportunity's custom field values.

            Reserved keys (set by the GHL import, matched case-insensitively):
            `ghlOpportunityId`, `ghlContactId`, `ghlPipeline`, `ghlStage`.
            Setting one, or changing its stored value, is refused with
            `400 VALIDATION_ERROR` (`error.field: customFields`). Reserved keys
            the opportunity already holds are kept even when this map leaves
            them out.
        source: { type: string }
        expectedCloseDate:
          type: integer
          format: int64
          description: Epoch milliseconds

    OpportunityUpdate:
      type: object
      description: All fields optional. Prefer `/status` and `/stage` for status/stage transitions.
      properties:
        pipelineId: { type: string }
        stageId: { type: string }
        name: { type: string }
        value: { type: number }
        currency: { type: string }
        assignedTo: { type: string }
        tags:
          type: array
          items: { type: string }
        customFields:
          type: object
          additionalProperties: true
          description: |
            Custom field values, keyed by field name.

            Reserved keys (set by the GHL import, matched case-insensitively):
            `ghlOpportunityId`, `ghlContactId`, `ghlPipeline`, `ghlStage`.
            Setting one is refused with `400 VALIDATION_ERROR`
            (`error.field: customFields`).
        source: { type: string }
        expectedCloseDate:
          type: integer
          format: int64
          description: Epoch milliseconds
        lostReason: { type: string }
        probabilityOverride:
          type: integer
          minimum: 0
          maximum: 100

    OpportunityStatusUpdate:
      type: object
      required: [status]
      properties:
        status:
          type: string
          enum: [open, won, lost, abandoned]
        lostReason:
          type: string
          description: Required when `status` is `lost`.

    OpportunityStageMove:
      type: object
      required: [stageId]
      properties:
        stageId:
          type: string
          description: Destination stage id. Must belong to the opportunity's current pipeline.
        beforeDealId:
          type: string
          description: Optional - place this opportunity immediately before the given opportunity id within the destination stage's ordered list.
        afterDealId:
          type: string
          description: Optional - place this opportunity immediately after the given opportunity id within the destination stage's ordered list.

    PipelineStage:
      type: object
      required: [id, name, position, isTerminal, requiredFields]
      properties:
        id: { type: string }
        name: { type: string }
        description:
          type:
            - string
            - "null"
        position: { type: number }
        color:
          type:
            - string
            - "null"
        probability:
          type:
            - integer
            - "null"
          minimum: 0
          maximum: 100
        isTerminal: { type: boolean }
        staleDealThresholdDays:
          type:
            - integer
            - "null"
        requiredFields:
          type: array
          items: { type: string }

    Pipeline:
      type: object
      required:
        - id
        - agencyId
        - subAccountId
        - name
        - isDefault
        - allowDuplicateOpportunities
        - staleDealEnabled
        - stages
        - createdAt
        - updatedAt
      properties:
        id: { type: string }
        agencyId: { type: string }
        subAccountId: { type: string }
        name: { type: string }
        description:
          type:
            - string
            - "null"
        isDefault: { type: boolean }
        allowDuplicateOpportunities:
          type: boolean
          description: When `false`, creating a second open opportunity for the same contact in this pipeline returns `DUPLICATE_OPPORTUNITY`. Pipelines created before this field existed are treated as `true`.
        staleDealEnabled: { type: boolean }
        staleDealThresholdDays:
          type:
            - integer
            - "null"
        staleDealColor:
          type:
            - string
            - "null"
        stages:
          type: array
          items: { $ref: "#/components/schemas/PipelineStage" }
        createdAt: { type: string, format: date-time }
        updatedAt: { type: string, format: date-time }

    # -----------------------------------------------------------------------
    # Conversational booking
    # -----------------------------------------------------------------------
    ServiceType:
      type: object
      description: |
        One line of the published price list. Everything here is something the
        business already tells a caller on the phone.
      required: [id, name, description, category, folder, price, currency, hasVariablePricing]
      properties:
        id:
          type: string
        name:
          type: string
          example: "Drain clean"
        description:
          type:
            - string
            - "null"
          example: "Up to 50ft of line, includes camera check"
        category:
          type:
            - string
            - "null"
          example: "Plumbing"
        folder:
          type:
            - string
            - "null"
          description: The group this service is filed under in the CRM.
          example: "Emergency call-outs"
        price:
          type: number
          example: 189
        currency:
          type: string
          example: "USD"
        hasVariablePricing:
          type: boolean
          description: |
            True when the real price depends on quantity or on options the
            customer picks. Quote `price` as a starting point, not a firm
            number, and offer a proper estimate.

    BookingEstimate:
      type: object
      description: |
        One quote belonging to the contact the conversation is with. The
        minimum a booking conversation needs: that it exists, what it totals,
        and whether it is still good.

        Deliberately has no title or description field. Both are free text a
        team types, and a quote title routinely carries the customer's name and
        address. See the endpoint description.
      required:
        [
          id,
          number,
          status,
          isApproved,
          total,
          currency,
          validUntil,
          isExpired,
          approvedAt,
          createdAt,
        ]
      properties:
        id:
          type: string
        number:
          type: string
          description: |
            The reference the customer sees on their copy. This is how a
            conversation refers to a quote, since there is no title.
          example: "EST-0104"
        status:
          type: string
          enum: [sent, viewed, accepted]
          description: |
            Drafts and quotes that were declined, expired or already invoiced
            are never returned.
        isApproved:
          type: boolean
          description: The customer has accepted this quote.
        total:
          type: number
          example: 2400
        currency:
          type: string
          example: "USD"
        validUntil:
          type:
            - string
            - "null"
          format: date-time
        isExpired:
          type: boolean
          description: |
            The expiry date has passed. The quote is still returned so the
            conversation can offer a re-quote rather than pretending it never
            existed.
        approvedAt:
          type:
            - string
            - "null"
          format: date-time
        createdAt:
          type: string
          format: date-time

# =============================================================================
# WEBHOOKS (OpenAPI 3.1 top-level webhooks)
# =============================================================================
webhooks:
  contact.deleted:
    post:
      operationId: webhookContactDeleted
      summary: Contact soft-deleted
      description: |
        Explicit opt-in reference-only event from reviewed contact soft-deletion paths.
        Restricted connections require policy 10, contacts:read, allowWebhooks and
        allowDeletedWebhooks. Existing approvals and subscriptions are not expanded.
        Merges, erasure and administrative purges are excluded.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required: [event, timestamp, data]
              properties:
                event: { const: "contact.deleted" }
                timestamp: { type: string, format: date-time }
                data:
                  type: object
                  additionalProperties: false
                  required: [deliveryMode, deleted, subAccountId, contactId]
                  properties:
                    deliveryMode: { const: "record-reference-v1" }
                    deleted: { const: true }
                    subAccountId: { type: string }
                    contactId: { type: string }
      responses:
        "200": { description: Webhook received }

  contact.created:
    post:
      operationId: webhookContactCreated
      summary: Contact created
      description: Fires when a new contact is created.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event:
                      const: "contact.created"
                    data:
                      $ref: "#/components/schemas/ContactCreatedEventData"
      responses:
        "200":
          description: Webhook received

  contact.updated:
    post:
      operationId: webhookContactUpdated
      summary: Contact updated
      description: Fires when a contact record is updated.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event:
                      const: "contact.updated"
                    data:
                      $ref: "#/components/schemas/ContactUpdatedEventData"
      responses:
        "200":
          description: Webhook received

  contact.lifecycle_changed:
    post:
      operationId: webhookContactLifecycleChanged
      summary: Contact lifecycle changed
      description: Fires when a contact's lifecycle stage changes.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event:
                      const: "contact.lifecycle_changed"
                    data:
                      $ref: "#/components/schemas/ContactLifecycleChangedEventData"
      responses:
        "200":
          description: Webhook received

  contact.tag_added:
    post:
      operationId: webhookContactTagAdded
      summary: Tag added to contact
      description: Fires when a tag is added to a contact.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event:
                      const: "contact.tag_added"
                    data:
                      $ref: "#/components/schemas/ContactTagAddedEventData"
      responses:
        "200":
          description: Webhook received

  message.received:
    post:
      operationId: webhookMessageReceived
      summary: Message received
      description: Fires when an inbound message is received on any channel.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event:
                      const: "message.received"
                    data:
                      $ref: "#/components/schemas/MessageReceivedEventData"
      responses:
        "200":
          description: Webhook received

  message.sent:
    post:
      operationId: webhookMessageSent
      summary: Message sent
      description: Fires when an outbound message is confirmed sent by the provider.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event:
                      const: "message.sent"
                    data:
                      $ref: "#/components/schemas/MessageStatusEventData"
      responses:
        "200":
          description: Webhook received

  message.delivered:
    post:
      operationId: webhookMessageDelivered
      summary: Message delivered
      description: Fires when an outbound message is confirmed delivered to the recipient.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event:
                      const: "message.delivered"
                    data:
                      $ref: "#/components/schemas/MessageStatusEventData"
      responses:
        "200":
          description: Webhook received

  message.failed:
    post:
      operationId: webhookMessageFailed
      summary: Message failed
      description: Fires when an outbound message fails to deliver or bounces.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event:
                      const: "message.failed"
                    data:
                      $ref: "#/components/schemas/MessageStatusEventData"
      responses:
        "200":
          description: Webhook received

  appointment.booked:
    post:
      operationId: webhookAppointmentBooked
      summary: Appointment booked
      description: Fires when a new appointment is booked.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event:
                      const: "appointment.booked"
                    data:
                      $ref: "#/components/schemas/AppointmentBookedEventData"
      responses:
        "200":
          description: Webhook received

  appointment.cancelled:
    post:
      operationId: webhookAppointmentCancelled
      summary: Appointment cancelled
      description: >-
        Fires when an appointment is cancelled, including authenticated
        cancellations from the dashboard, self-service customer cancellations
        via the booking-token link, and CANCEL-keyword SMS replies. Payload
        shape matches `appointment.booked` for integration ergonomics.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event:
                      const: "appointment.cancelled"
                    data:
                      $ref: "#/components/schemas/AppointmentBookedEventData"
      responses:
        "200":
          description: Webhook received

  appointment.rescheduled:
    post:
      operationId: webhookAppointmentRescheduled
      summary: Appointment rescheduled
      description: >-
        Fires when an existing appointment is moved to a new time, including
        operator-driven reschedules and self-service customer reschedules via
        the booking-token link. Payload shape matches `appointment.booked`.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event:
                      const: "appointment.rescheduled"
                    data:
                      $ref: "#/components/schemas/AppointmentBookedEventData"
      responses:
        "200":
          description: Webhook received

  appointment.confirmed:
    post:
      operationId: webhookAppointmentConfirmed
      summary: Appointment confirmed
      description: >-
        Fires when an operator transitions an appointment to the
        `confirmed` status. Useful for downstream automations that gate
        on confirmation (e.g. fulfilment, prep tasks, customer comms).
        Payload shape matches `appointment.booked`.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event:
                      const: "appointment.confirmed"
                    data:
                      $ref: "#/components/schemas/AppointmentBookedEventData"
      responses:
        "200":
          description: Webhook received

  appointment.completed:
    post:
      operationId: webhookAppointmentCompleted
      summary: Appointment completed
      description: >-
        Fires when an appointment is marked `completed`. Useful for
        review requests, follow-up campaigns, and revenue-event tracking
        in ad platforms. Payload shape matches `appointment.booked`.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event:
                      const: "appointment.completed"
                    data:
                      $ref: "#/components/schemas/AppointmentBookedEventData"
      responses:
        "200":
          description: Webhook received

  appointment.no_show:
    post:
      operationId: webhookAppointmentNoShow
      summary: Appointment no-show
      description: >-
        Fires when an appointment is marked `no_show`. The contact's
        `noShowCount` is incremented on the same transition; subscribers
        can drive re-engagement automations off this event. Payload
        shape matches `appointment.booked`.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event:
                      const: "appointment.no_show"
                    data:
                      $ref: "#/components/schemas/AppointmentBookedEventData"
      responses:
        "200":
          description: Webhook received

  opportunity.created:
    post:
      operationId: webhookOpportunityCreated
      summary: Opportunity created
      description: Fires when a new opportunity is created in a pipeline.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event:
                      const: "opportunity.created"
                    data:
                      $ref: "#/components/schemas/OpportunityCreatedEventData"
      responses:
        "200":
          description: Webhook received

  opportunity.stage_changed:
    post:
      operationId: webhookOpportunityStageChanged
      summary: Opportunity stage changed
      description: Fires when an opportunity moves to a different pipeline stage.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event:
                      const: "opportunity.stage_changed"
                    data:
                      $ref: "#/components/schemas/OpportunityStageChangedEventData"
      responses:
        "200":
          description: Webhook received

  opportunity.won:
    post:
      operationId: webhookOpportunityWon
      summary: Opportunity won
      description: Fires when an opportunity is marked as won.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event:
                      const: "opportunity.won"
                    data:
                      $ref: "#/components/schemas/OpportunityWonEventData"
      responses:
        "200":
          description: Webhook received

  opportunity.lost:
    post:
      operationId: webhookOpportunityLost
      summary: Opportunity lost
      description: Fires when an opportunity is marked as lost.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event:
                      const: "opportunity.lost"
                    data:
                      $ref: "#/components/schemas/OpportunityLostEventData"
      responses:
        "200":
          description: Webhook received

  form.submitted:
    post:
      operationId: webhookFormSubmitted
      summary: Form submitted
      description: Fires when a public form is submitted.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event:
                      const: "form.submitted"
                    data:
                      $ref: "#/components/schemas/FormSubmittedEventData"
      responses:
        "200":
          description: Webhook received

  invoice.paid:
    post:
      operationId: webhookInvoicePaid
      summary: Invoice paid
      description: Fires when an invoice payment is received.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event:
                      const: "invoice.paid"
                    data:
                      $ref: "#/components/schemas/InvoicePaidEventData"
      responses:
        "200":
          description: Webhook received

  task.created:
    post:
      operationId: webhookTaskCreated
      summary: Task created
      description: Fires when a task is created (UI, API, or workflow action).
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event: { const: "task.created" }
                    data: { $ref: "#/components/schemas/TaskEventData" }
      responses:
        "200": { description: Webhook received }

  task.updated:
    post:
      operationId: webhookTaskUpdated
      summary: Task updated
      description: Fires when any field on a task changes. Includes `changedFields`.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event: { const: "task.updated" }
                    data: { $ref: "#/components/schemas/TaskEventData" }
      responses:
        "200": { description: Webhook received }

  task.completed:
    post:
      operationId: webhookTaskCompleted
      summary: Task completed
      description: Fires when a task is marked completed. Includes `completedAt` (epoch ms).
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event: { const: "task.completed" }
                    data: { $ref: "#/components/schemas/TaskEventData" }
      responses:
        "200": { description: Webhook received }

  task.deleted:
    post:
      operationId: webhookTaskDeleted
      summary: Task deleted
      description: Fires when a task is permanently deleted. Reflects state at deletion.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event: { const: "task.deleted" }
                    data: { $ref: "#/components/schemas/TaskEventData" }
      responses:
        "200": { description: Webhook received }

  opportunity.updated:
    post:
      operationId: webhookOpportunityUpdated
      summary: Opportunity updated
      description: Fires when any field on an opportunity changes. Includes `changedFields`.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event: { const: "opportunity.updated" }
                    data: { $ref: "#/components/schemas/OpportunityEventData" }
      responses:
        "200": { description: Webhook received }

  opportunity.deleted:
    post:
      operationId: webhookOpportunityDeleted
      summary: Opportunity deleted
      description: Fires when an opportunity is soft-deleted. Reflects state at deletion.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event: { const: "opportunity.deleted" }
                    data: { $ref: "#/components/schemas/OpportunityEventData" }
      responses:
        "200": { description: Webhook received }

  task.contact_deleted:
    post:
      operationId: webhookTaskContactDeleted
      summary: Open task cancelled by a contact deletion
      description: Reference-only child of a dashboard or API contact deletion. Bounded; see cascadeTruncated.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event: { const: "task.contact_deleted" }
                    data: { $ref: "#/components/schemas/ContactCascadeEventData" }
      responses:
        "200": { description: Webhook received }

  appointment.contact_deleted:
    post:
      operationId: webhookAppointmentContactDeleted
      summary: Upcoming appointment cancelled by a contact deletion
      description: Reference-only child of a dashboard or API contact deletion. Bounded; see cascadeTruncated.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/WebhookPayloadEnvelope"
                - type: object
                  properties:
                    event: { const: "appointment.contact_deleted" }
                    data: { $ref: "#/components/schemas/ContactCascadeEventData" }
      responses:
        "200": { description: Webhook received }

# Record restrictions apply to newly approved Standard v2 and OAuth grants only.
x-record-grants:
  version: 11
  defaultVersionWithoutTaskDetails: 10
  taskDetails: explicit-allowTaskDetails-version-11
  taskDetailsLifecycle: additional-allowLifecycle-for-archive-restore-and-completion
  taskDetailsDependencies: additional-allowRelink-and-independent-both-task-access
  taskDetailsDuplicate: location-wide-only
  legacyDeletedWebhookPolicyVersions: [9]
  legacyWebhookPolicyVersions: [8]
  legacyRemovalPolicyVersions: [7]
  legacyLifecyclePolicyVersions: [6]
  legacyRelationshipPolicyVersions: [5]
  legacyDeletePolicyVersions: [4]
  legacyCreatePolicyVersions: [3]
  legacyUpdatePolicyVersions: [2]
  legacyReadPolicyVersions: [1]
  supportedScopes: ["contacts:read", "contacts:write", "contacts:delete", "tasks:read", "tasks:write", "tasks:delete", "opportunities:read", "opportunities:write", "opportunities:delete", "webhooks:read", "webhooks:write", "webhooks:delete"]
  filteredWrites:
    methods: [PATCH, POST, DELETE, PUT]
    idempotencyKey: required
    response: receipt-only
    fields: see-authorization-boundaries
    creation: explicit-allowCreate-approval-own-or-team
    contactUpserts: explicit-allowContactUpsert-approval
    reassignment: explicit-allowReassign-approval-version-5
    relationships: explicit-allowRelink-approval-version-5
    relationshipRemovals: explicit-null-under-version-7-allowRelink-task-only
    ownerRemovals: explicit-null-under-version-7-allowReassign
    removalPostcondition: target-must-remain-within-current-record-and-role-access
    opportunityContactRemoval: denied-required-relationship
    relationshipRetries: exact-state-and-old-new-access-rechecked
    deletion: explicit-delete-scope-bounded-cleanup
    oauthDeletion: restricted-record-consent-required
    lifecycleActions: explicit-allowLifecycle-approval-version-6
    lifecycleContactAccess: opportunity-actions-require-linked-contact-read-and-write
    lifecyclePositioning: append-only-no-neighbor-ids
  modes: [own, team, selected]
  selectedRecordLimit: 100
  webhooks:
    approval: explicit-allowWebhooks-version-8
    deliveryMode: record-reference-v1
    payload: authorized-record-ids-only
    authorization: queue-retry-and-before-each-network-request
    redirects: same-origin
    deletionEvents:
      approval: additional-allowDeletedWebhooks-version-9
      events: [task.deleted, opportunity.deleted]
      marker: data.deleted-true
      proof: private-transactional-ownership-and-relationship-projection
      opportunityInstance: timestamp-and-deletion-counter
      unsupportedPaths: project-cascades-and-administrative-purges
      contactDeletionEvent: policy-10-allowDeletedWebhooks-contact-read
    linkedEvents:
      approval: additional-allowLinkedEvents-version-14
      events: [form.submitted, review.received, appointment.booked, appointment.cancelled, appointment.rescheduled, appointment.confirmed, appointment.completed, appointment.no_show]
      contactCascadeEvents: [task.contact_deleted, appointment.contact_deleted]
      contactCascadeApproval: additional-allowDeletedWebhooks
      payload: "#/components/schemas/LinkedEventReferenceData"
      boundary: linked-contact-record-grant-rechecked-at-queue-retry-and-send
      eventOnlyScopes: ["forms:read", "reviews:read", "appointments:read"]
      eventOnlyScopesOpenNoRoutes: true
      unlinkedRecords: not-sent
      existingGrants: reconsent-required
    locationWideOAuthEvents:
      approval: consent-eventPolicyVersion-14
      events: [appointment.booked, appointment.cancelled, appointment.rescheduled, appointment.confirmed, appointment.completed, appointment.no_show, task.contact_deleted, appointment.contact_deleted]
      payload: record-reference-v1
    unsupportedEventFamilies: denied
  unsupportedOperations: deny
  legacyKeys: unchanged
  documentation: docs/integrations/integration-authorization-boundaries.md
