> For the complete documentation index, see [llms.txt](https://docs.tiny.plus/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tiny.plus/api/concepts/requests.md).

# Requests, responses and errors

## Where to send requests

Every endpoint lives under `https://api.tiny.plus/v2`, apart from `https://api.tiny.plus/me`, which returns the person a token belongs to.

## Authentication

Send an access token in the `Authorization` header of every request:

```
Authorization: Bearer {{user_access_token}}
```

[Getting access](/api/getting-access.md) explains which kind of token to use. A token acts as one person, and can only see and change what they can in tiny+. [Permissions and confidential records](/api/concepts/permissions.md) has the details.

## Choosing an account

A token belongs to a person, not to an account. Some people belong to more than one tiny+ account. To choose which account a request is for, add `account={account id}` to the query string, or to a form-encoded body. It isn't read from a JSON body.

Without it, the request uses the person's first active account. `GET https://api.tiny.plus/me` returns the person, their account under `account`, and any other accounts under `extra_accounts`.

If the account you ask for isn't one of the person's active accounts, the request fails with `403` and `{"error": "That account is not active."}`.

## Sending data

* Send request bodies as JSON with `Content-Type: application/json`, or form-encoded.
* `PATCH` and `PUT` do the same thing: only the fields you send are changed.
* URL-encode values in the query string, especially `<` (`%3C`), `>` (`%3E`), `&` and spaces.
* Call the API from your server. It only accepts requests from browser code running on tiny+'s own sites.

## Responses

* Responses are JSON.
* Most values come back as strings, including ids, numbers and dates, for example `"id": "1343"`. You can send them either as strings or as numbers.
* Dates are `YYYY-MM-DD`. Date-times are `YYYY-MM-DD hh:mm:ss` on a 24-hour clock, sometimes with fractional seconds, for example `2024-09-17 04:03:28.0000000`.
* Timestamps such as `created_date` and `modified_date` are in UTC, whatever the account's time zone. Filters on them compare in UTC too.
* When you get one record, each field that holds another record's id comes with a `{field}_name` companion holding that record's name, so you don't have to look it up.
* An empty object comes back as an empty array, `[]`. For example, `related` on a record with no links is `[]`, not `{}`. Treat the two alike.

## Reading your own changes

Reads may be served from a cache. If you read a record straight after changing it, add `use_cache=0` to be sure you get the latest version.

## Errors

When a request fails, the response body has an `error` key:

| Status | When                                                                                                                          | Example body                                                                      |
| ------ | ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| `400`  | A parameter or the body is wrong, a filter can't be applied, or a record can't be created (including for lack of permission). | `{"error": "'limit' maximum is 1000."}`                                           |
| `401`  | The token is missing, invalid, expired or revoked.                                                                            | `{"error": "access_denied", "error_description": "...", "hint": "..."}`           |
| `403`  | The token's user may not do this, or the account chosen with `account=` isn't active.                                         | `{"error": "You may not edit this record: it is not one you own or administer."}` |
| `404`  | There is no such record, or no such endpoint.                                                                                 | `{"error": "Record not found"}`                                                   |
| `410`  | The record has been deleted.                                                                                                  | `{"error": "This record has been deleted."}`                                      |
| `500`  | Something went wrong on our side.                                                                                             | `{"error": "A system error occurred. Please contact tiny support."}`              |

{% hint style="info" %}
A few requests report a failure with a `200` status and an `error` key. A change that couldn't be saved can also come back as `200` with `{"results": false}`. Check the body as well as the status.
{% endhint %}
