> ## Documentation Index
> Fetch the complete documentation index at: https://docs.embedreach.com/llms.txt
> Use this file to discover all available pages before exploring further.

# List tenant usage

> Returns every tenant billable over the requested window, paginated. A tenant soft-deleted partway through the window is still listed, with deletedAt set, because they were billable for the earlier part of it. startDate and endDate are both required and must be YYYY-MM-DD calendar days; any other format is rejected. Both days are included in full, so September is startDate=2026-09-01 and endDate=2026-09-30. A tenant deleted at the very start of startDate is not listed, having been billable for none of it.



## OpenAPI

````yaml GET /partner/tenant-usage
openapi: 3.1.0
info:
  title: Reach API
  version: 1.0.0
  description: API documentation for Reach platform
servers:
  - url: https://api.embedreach.com
    description: Production server
security: []
tags:
  - name: Default Partner Resources
    x-reach-introduction: >-
      ---

      title: 'Default Partner Resources'

      description: 'Convenience endpoints for default resource schemas'

      ---


      Reach provides three default resource schemas that are available to
      partners upon request: **customers**, **locations**, and **transactions**.
      These schemas come pre-configured with common fields and can be used
      immediately once enabled for your partner account.


      <Note>
        These default schemas can be customized to match your specific data structure. See [Schema Definitions](/api-reference/endpoint/get-partner-schema-definitions) for information on customizing or creating your own schemas.
      </Note>


      ## Available Default Schemas


      - **customers**: For storing customer/user data

      - **locations**: For storing business location data  

      - **transactions**: For storing transaction/order data


      ## Using Default Resource Endpoints


      The endpoints in this section provide convenient shortcuts for all CRUD
      operations on the default resource schemas. These endpoints are equivalent
      to using the generic [Partner
      Resources](/api-reference/endpoint/get-api-resources-schemadefinitionnameorid)
      endpoints with the schema name (`customers`, `locations`, or
      `transactions`).


      Operations supported:

      - **Create**: Single and batch upload

      - **Read**: List all resources or get by external ID

      - **Update**: Patch single resource or batch patch

      - **Delete**: Delete single resource or batch delete
  - name: Schema Definitions
    x-reach-introduction: >-
      ---

      title: 'Overview'

      description: 'Define the shape of your data before you send it'

      ---


      A **schema definition** describes your data as it exists in your system —
      a JSON Schema for your customers, transactions, locations, or any custom
      record type. These endpoints let you create, read, update, and list those
      definitions. Defining a schema is self-service; you don't need to wait on
      Reach to do it for you.


      <Note>

      **New to this? Read the concepts first — they'll save you a redesign.**
      Schema definitions are one half of a two-part model, and the shape you
      choose here determines what your tenants can segment and message on later.


      - [How Reach models your data](/data-sharing/data-model) — the three
      canonical concepts (contact, transaction, location), and the
      definition-vs-mapping distinction.

      - [Custom Schemas](/data-sharing/custom-schemas) — the JSON Schema format,
      `$ref` references between schemas, categories, and PII annotations.

      - [Data Sync Setup](/onboarding/data-sync-setup) — how defining schemas
      fits into onboarding.

      </Note>


      A definition on its own is just a shape Reach stores. To turn it into a
      contact, transaction, or location, pair it with a [Schema
      Mapping](/api-reference/endpoint/get-partner-schema-mappings).


      <Warning>

      Validation is strict, and it protects existing data: you can always
      **add** fields, but **removing, renaming, or retyping** a field that
      resources already use is restricted, and fields that live tenant segments
      or merge fields depend on are protected. Iterate freely before go-live; be
      deliberate after.

      </Warning>
  - name: Schema Mappings
    x-reach-introduction: >-
      ---

      title: 'Overview'

      description: 'Tell Reach how to read your data as its core concepts'

      ---


      A **schema mapping** tells Reach how to interpret your [schema
      definitions](/api-reference/endpoint/get-partner-schema-definitions) in
      terms of its three canonical concepts — **contact**, **transaction**, and
      **location**. It's the step that says "the `email` field on this schema is
      the contact's email," "this schema is a `transactions_schema` and
      `transactionTotal` is the amount," and so on.


      <Note>

      **Definition vs. mapping is the distinction partners most often trip on —
      read this before you map.**


      - A **definition** is *the shape of your data* (your field names, your
      structure).

      - A **mapping** is *how Reach reads that shape as its concepts*.


      Two steps, two parts of the UI. Start here:


      - [How Reach models your data](/data-sharing/data-model) — the concepts
      and the definition-vs-mapping split.

      - [Custom Schemas → Partner Schema
      Mappings](/data-sharing/custom-schemas#partner-schema-mappings) — the full
      mapping field reference for contacts, transactions, and locations.

      </Note>


      Define your schemas first, then map them. A mapping references a schema
      definition by ID, so the definition must exist before you can map it.
  - name: Tenants
    x-reach-introduction: >-
      ---

      title: 'Overview'

      description: 'Create and manage the businesses you serve'

      ---


      A **tenant** is one of your customers — a business you manage on behalf of
      your platform. Creating one is the first call you make against the Reach
      API: it returns the tenant `id` that every other tenant-scoped call, JWT,
      and embedded UI session refers back to.


      ## Identifying a tenant


      A tenant has two identifiers: the Reach `id` returned by **Create
      Tenant**, and the `externalId` you supply — your own key for the same
      business. **Get**, **Update**, **Delete**, and **Reactivate** each accept
      either one in the path, so you never have to store the Reach `id` if you
      would rather look tenants up by your own.


      ## Lifecycle


      <Steps>
        <Step title="Create">
          `POST /partner/tenants` with a name and your `externalId`. Reach provisions the tenant's default resources asynchronously, so some of them appear shortly after the response returns rather than in it.
        </Step>
        <Step title="Update">
          `PATCH /partner/tenants/{id}` — every field is optional, so send only what changed.
        </Step>
        <Step title="Deactivate">
          `DELETE /partner/tenants/{id}` deactivates rather than destroys. The tenant drops out of **List Tenants** unless you pass `includeDeleted=true`, and **Get Tenant** keeps returning it with `deletedAt` set.
        </Step>
        <Step title="Reactivate">
          `POST /partner/tenants/{id}/reactivate` restores a deactivated tenant with its data intact.
        </Step>
      </Steps>


      ## What lives on a tenant


      | Field | What it is for |

      | --- | --- |

      | `name`, `website` | How the business is identified across Reach, and the
      site the tracking snippet reports from |

      | `locations` | The business's physical addresses |

      | `branding` | Logo, colors, brand name, and brand voice — what the
      embedded UI and generated content adopt |

      | `timezone`, `businessHours` | When the business is open — see below |

      | `smsOptInImageUrls` | Evidence of how the business captures SMS consent,
      used for carrier registration |


      <Note>

      If your partner account is configured with a location schema, the
      `locations` you send are stored as location resources rather than on the
      tenant record. Reads return them either way, so the field behaves the same
      from your side.

      </Note>


      ### Merged fields and replaced fields


      On update, `branding` is **merged** key by key into what is already
      stored, so you can send just the keys you want to change. `locations`,
      `smsOptInImageUrls`, and `businessHours` are **replaced wholesale** — send
      the complete value every time, or you will drop what you left out.


      ## Listing tenants


      **List Tenants** is cursor-paginated through `cursor` and `limit` (default
      100). Narrow it with `search`, which matches on name, external id, or
      website; order it with `orderBy` and `orderDirection`; include deactivated
      tenants with `includeDeleted=true`. For portfolio-wide sweeps, pass
      `fields` — a comma-separated projection such as `id,name` — to trim the
      payload to what you actually read.


      ## Timezone and business hours


      `timezone` and `businessHours` record when a tenant is open. Both are
      accepted on **Create Tenant** and **Update Tenant**, and returned by **Get
      Tenant**. They sit on the business itself rather than on any one product,
      so one schedule serves every Reach feature that needs it — AI Voice uses
      `timezone` today to give the agent the tenant's local time.


      You are the source of truth for both. Reach never infers a timezone from a
      tenant's address, and an unset value means *not configured* — it does not
      mean always open, and it does not mean always closed.


      `timezone` is any IANA timezone id — `America/New_York`, `Europe/London`,
      `Pacific/Honolulu`. Send `null` to clear it.


      `businessHours` is an object carrying all seven weekday keys, `monday`
      through `sunday`. Each key is either `null` or an empty list (closed that
      day), or a list holding exactly one interval of 24-hour `HH:MM` times:


      ```json

      {
        "monday": [{ "open": "09:00", "close": "17:00" }],
        "tuesday": [{ "open": "09:00", "close": "17:00" }],
        "wednesday": [{ "open": "09:00", "close": "17:00" }],
        "thursday": [{ "open": "09:00", "close": "17:00" }],
        "friday": [{ "open": "09:00", "close": "20:00" }],
        "saturday": [{ "open": "10:00", "close": "14:00" }],
        "sunday": null
      }

      ```


      Those are local wall-clock times in the tenant's `timezone`, never UTC.
      Reach reads them against the tenant's local clock at the instant it
      evaluates them, so daylight saving shifts resolve on their own. **The
      opening time is inclusive and the closing time is exclusive** — against
      `09:00`–`17:00`, a moment at exactly `09:00` counts as in hours, and a
      moment at exactly `17:00` does not.


      <Warning>

      The schedule format is deliberately narrow for now:


      - **One interval per weekday.** Split shifts — a midday closure — are not
      supported yet.

      - **`open` must be earlier than `close`.** An interval cannot cross
      midnight, so overnight hours such as `20:00` to `02:00` cannot be
      expressed yet.

      - **All seven weekdays are required, and an update replaces the whole
      schedule.** There is no per-day merge: send every day on each update, and
      send `null` for the whole field to clear the schedule.

      </Warning>


      <Note>

      Tenants can also edit their own timezone and hours from the Voice settings
      in the embedded Reach UI. Those edits write to the same business record,
      so **Get Tenant** can return values you did not send. Re-read the tenant
      if your system needs to stay in sync.

      </Note>
paths:
  /partner/tenant-usage:
    get:
      tags:
        - Tenant Usage
      summary: List tenant usage
      description: >-
        Returns every tenant billable over the requested window, paginated. A
        tenant soft-deleted partway through the window is still listed, with
        deletedAt set, because they were billable for the earlier part of it.
        startDate and endDate are both required and must be YYYY-MM-DD calendar
        days; any other format is rejected. Both days are included in full, so
        September is startDate=2026-09-01 and endDate=2026-09-30. A tenant
        deleted at the very start of startDate is not listed, having been
        billable for none of it.
      parameters:
        - schema:
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
          required: true
          name: startDate
          in: query
        - schema:
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
          required: true
          name: endDate
          in: query
        - schema:
            type: string
          required: false
          name: cursor
          in: query
        - schema:
            type: integer
            exclusiveMinimum: 0
            maximum: 100
            default: 25
          required: false
          name: limit
          in: query
      responses:
        '200':
          description: Status 200 response
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      results:
                        type: array
                        items:
                          type: object
                          properties:
                            tenantId:
                              type: string
                            externalId:
                              type:
                                - string
                                - 'null'
                            name:
                              type: string
                            deletedAt:
                              type:
                                - string
                                - 'null'
                              format: date-time
                            resources:
                              type: object
                              properties:
                                phoneNumbers:
                                  type: object
                                  properties:
                                    total:
                                      type: integer
                                      minimum: 0
                                    tollFree:
                                      type: integer
                                      minimum: 0
                                    local:
                                      type: integer
                                      minimum: 0
                                  required:
                                    - total
                                    - tollFree
                                    - local
                                locations:
                                  type: integer
                                  exclusiveMinimum: 0
                              required:
                                - phoneNumbers
                                - locations
                            features:
                              type: array
                              items:
                                oneOf:
                                  - type: object
                                    properties:
                                      feature:
                                        type: string
                                        enum:
                                          - assist
                                      active:
                                        type: boolean
                                      usage:
                                        type: object
                                        properties:
                                          callCount:
                                            type: integer
                                            minimum: 0
                                          callDurationSeconds:
                                            type: integer
                                            minimum: 0
                                        required:
                                          - callCount
                                          - callDurationSeconds
                                    required:
                                      - feature
                                      - active
                                      - usage
                                  - type: object
                                    properties:
                                      feature:
                                        type: string
                                        enum:
                                          - engage
                                      active:
                                        type: boolean
                                      usage:
                                        type: object
                                        properties:
                                          emailsSent:
                                            type: integer
                                            minimum: 0
                                          smsSent:
                                            type: integer
                                            minimum: 0
                                        required:
                                          - emailsSent
                                          - smsSent
                                    required:
                                      - feature
                                      - active
                                      - usage
                                  - type: object
                                    properties:
                                      feature:
                                        type: string
                                        enum:
                                          - reputation
                                      active:
                                        type: boolean
                                      usage:
                                        type: object
                                        properties:
                                          emailsSent:
                                            type: integer
                                            minimum: 0
                                          smsSent:
                                            type: integer
                                            minimum: 0
                                        required:
                                          - emailsSent
                                          - smsSent
                                    required:
                                      - feature
                                      - active
                                      - usage
                                  - type: object
                                    properties:
                                      feature:
                                        type: string
                                        enum:
                                          - ads
                                      active:
                                        type: boolean
                                      usage:
                                        type: object
                                        properties:
                                          googleAdSpend:
                                            type: object
                                            properties:
                                              reachManaged:
                                                type: string
                                                pattern: ^(0|[1-9]\d*)\.\d{2}$
                                              other:
                                                type: string
                                                pattern: ^(0|[1-9]\d*)\.\d{2}$
                                            required:
                                              - reachManaged
                                              - other
                                          metaAdSpend:
                                            type: object
                                            properties:
                                              reachManaged:
                                                type: string
                                                pattern: ^(0|[1-9]\d*)\.\d{2}$
                                              other:
                                                type: string
                                                pattern: ^(0|[1-9]\d*)\.\d{2}$
                                            required:
                                              - reachManaged
                                              - other
                                        required:
                                          - googleAdSpend
                                          - metaAdSpend
                                    required:
                                      - feature
                                      - active
                                      - usage
                          required:
                            - tenantId
                            - externalId
                            - name
                            - deletedAt
                            - resources
                            - features
                      pagination:
                        type: object
                        properties:
                          hasNextPage:
                            type: boolean
                          cursor:
                            type:
                              - string
                              - 'null'
                          total:
                            type: number
                        required:
                          - hasNextPage
                    required:
                      - results
                      - pagination
                required:
                  - success
        '400':
          description: Bad Request - Validation or request error
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                      - false
                    default: false
                  message:
                    type: string
                    description: Error message describing what went wrong
                  errors:
                    type: array
                    items:
                      type: string
                    description: Optional array of specific validation errors
                required:
                  - message

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.