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

# Changelog

> What changed in the TeamCare Vendor API and how to migrate.

**November 7, 2026**

v1 sunset

Support for the v1 Vendor API (`https://app.teamcaredental.com/api/v1/vendors`) ends on **November 7, 2026**, the end of the first week of November. After that date v1 requests are no longer served. Move to v2 before then.

**October 26, 2026**

Vendor API v2

## Vendor API v2

v2 keeps every data endpoint, response shape, filter and pagination rule from v1. **Only two things change: the base URL and how you address a location.**

### New base URL

| | v1 | v2 |
| - | - | - |
| Base URL | `https://app.teamcaredental.com/api/v1/vendors` | `https://api.teamcaredental.com/api/v2/vendors` |

### `location_id` is gone from data URLs

In v1 every data route carried the location in the path (`/locations/{location_id}/patients`). In v2 you request a **slot** for a location once, then send the returned `request_key` in the `X-Vendor-Request-Key` header. The data routes have no `location_id`.

| v1 | v2 |
| - | - |
| `GET /locations/{location_id}/patients` | `GET /patients` + header `X-Vendor-Request-Key` |
| `GET /locations/{location_id}/appointments` | `GET /appointments` + header `X-Vendor-Request-Key` |
| `GET /locations/{location_id}/daily/stats` | `GET /daily/stats` + header `X-Vendor-Request-Key` |
| `POST /locations/{location_id}/dashboard/goals` | `POST /dashboard/goals` + header `X-Vendor-Request-Key` |

The same pattern applies to every location-scoped endpoint.

### New endpoint: request a slot

`POST /locations/{location_id}/slots` returns a `request_key` for that location.

```json theme={null}
{
  "data": {
    "id": "1",
    "type": "slot",
    "attributes": {
      "request_key": "a1292639f455cf0",
      "requested_at": "2026-10-26T12:00:00.000Z",
      "expires_at": "2026-10-26T18:00:00.000Z"
    }
  }
}
```

### Slot rules

* A `request_key` is valid for **6 hours**, the same lifetime as the access token.
* A firm can hold at most **10 active slots** at a time, so data for at most 10 locations can be pulled concurrently. Requesting an 11th slot invalidates the oldest `request_key` immediately. To raise this limit, contact TeamCare support.
* The same location's slot can be re-requested only once every **2 minutes**. Inside the cooldown the slot endpoint returns `429` with `retry_after` in seconds.
* The slot endpoint accepts at most **10 requests per 10 seconds** per token.
* A data request with a missing, expired or trimmed `request_key` returns `401 {"errors": "Invalid, expired or missing request key"}`.

The recommended pattern is to request a slot, pull all of that location's data, then move to the next location. If you fan out across locations in parallel, keep the fan-out at or below your quota.

### `GET /locations` is now paginated

v1 returned the full list. v2 returns a `pagy` object alongside `data`; use the `page` parameter.

### Unchanged

* `POST /auth/token`, `client_id` / `client_secret`, and the 6-hour JWT.
* `GET /organizations`.
* Ransack `q` filters, `q[fetch_modified_since]`, `after` / `items` / `page` pagination.
* Every response shape.

### Migration checklist

**1. Change the base URL**

Point your client at `https://api.teamcaredental.com/api/v2/vendors`.

**2. Request a slot per location**

After listing locations, call `POST /locations/{location_id}/slots` once for the location you are about to sync and keep its `request_key`.

**3. Drop the location from data paths**

Remove `/locations/{location_id}` from every data URL and add the header `X-Vendor-Request-Key: <request_key>`.

**4. Pull the whole location, then move on**

Fetch everything you need for that location before requesting the next slot. Keep parallel locations at or below 10.


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