> 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/endpoints/records.md).

# Records

Projects, companies, contacts and every other record type work the same way. This page covers the requests they share. Each record type's page covers what's particular to it, and lists its fields.

In the requests below, `{type}` is the record type's URL name, such as `projects`. The [Endpoints](/api/endpoints.md) page lists them all.

## List records

<mark style="color:blue;">`GET`</mark> `https://api.tiny.plus/v2/{type}`

Returns a page of records, which you can filter, sort and page through. [Listing, filtering and paging](/api/concepts/listing.md) covers every parameter.

```bash
curl "https://api.tiny.plus/v2/projects?record_status=active&sort=modified_date%20desc&limit=2&return_format=array&with_related=0" \
  -H "Authorization: Bearer {{user_access_token}}"
```

```javascript
{
    "total_records": 163,
    "returned_records": 2,
    "records": [
        { "id": "62388", "name": "Example Project", "record_status": "active", ... },
        { "id": "62385", "name": "Second Example Project", "record_status": "active", ... }
    ]
}
```

## Get a record

<mark style="color:blue;">`GET`</mark> `https://api.tiny.plus/v2/{type}/{{id}}`

| Parameter      | Description                                                                                                                                      |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `with_related` | Default `0`. Set it to `1` to include the records this one is linked to, in a `related` object. See [Linking records](/api/concepts/linking.md). |
| `with_health`  | Adds a `health` object, with the record's `rating` from 0 to 100 and the `reasons` behind it.                                                    |
| `use_cache`    | Set it to `0` to be sure of the latest version, straight after a change.                                                                         |

```bash
curl "https://api.tiny.plus/v2/projects/{{id}}" \
  -H "Authorization: Bearer {{user_access_token}}"
```

{% tabs %}
{% tab title="200 The record." %}

```javascript
{
    "id": "1343",
    "flavour": "projects",
    "name": "Example Project",
    "record_status": "active",
    "assigned_user": "1231",
    "primary_company_id": "1237",
    "primary_company_id_name": "Auchenflower Aged Care",
    "record_url": "https://crm.tiny.plus/project/1343",
    "perm_edit": true,
    "perm_delete": true,
    "show_obscured": false,
    "created_user_record": { "id": "1231", "name": "Nick Smith", "role": "Director", "email": "nick@example.com", "record_url": "https://crm.tiny.plus/staff/1231", "hero_thumb_uri": "…" },
    "subscribers": [{ "id": "1231", "name": "Nick Smith" }, { "id": "191", "name": "Maya Lin" }],
    ...
}
```

{% endtab %}

{% tab title="404 There is no such record." %}

```javascript
{
    "error": "Record not found"
}
```

{% endtab %}

{% tab title="410 The record has been deleted." %}

```javascript
{
    "error": "This record has been deleted."
}
```

{% endtab %}
{% endtabs %}

A record read this way also names three people: `assigned_user_record`, `created_user_record` and `modified_user_record`, each with the team member's `id`, `name`, `role`, `email`, `record_url` and `hero_thumb_uri`, or `null`. They are named even if they have since left the team. `subscribers` lists the record's followers, the active team members who follow it, each with `id` and `name`. A list of records carries `assigned_user_record` alone, and no followers.

## Get a record's change history

<mark style="color:blue;">`GET`</mark> `https://api.tiny.plus/v2/{type}/{{id}}/history`

Returns the changes made to a record's fields, newest first, as an array:

```javascript
[
    {
        "changeid": "4326",
        "action": "UPDATE",
        "record_id": "1343",
        "field_name": "project_number",
        "field_old": "2019-044",
        "field_new": "2020-001",
        "created_user": "1231",
        "created_date": "2020-05-07 10:02:31.000",
        "created_date_orig": "2020-05-07 00:02:31.0000000",
        ...
    },
    ...
]
```

`created_user` made the change. `field_old` and `field_new` are the stored values.

* History only covers changes to the fields tiny+ tracks for that record type. It doesn't cover the record's creation, its tags, links or custom fields.
* Unlike the rest of the API, `created_date` here is in Australia/Sydney time, whatever the account's time zone. `created_date_orig` is the same moment in UTC, so use that. Each change also comes with the date formatted in several other ways.
* A record with no tracked changes answers `404` `{"error": "Could not find history."}`.
* A confidential record's history is only available to people who can see the record. Anyone else gets `403` `{"error": "This record is confidential."}`.

## Create a record

<mark style="color:green;">`POST`</mark> `https://api.tiny.plus/v2/{type}`

Send the new record's fields as JSON, or form-encoded. `name` is the only field every record type requires. Some record types require others, which their field references mark as required.

| Parameter       | Description                                                  |
| --------------- | ------------------------------------------------------------ |
| `return_record` | Add this to get the new record back, instead of just its id. |
| `dont_track`    | See [Changing records quietly](#changing-records-quietly).   |

```bash
curl -X POST "https://api.tiny.plus/v2/projects" \
  -H "Authorization: Bearer {{user_access_token}}" \
  -H "Content-Type: application/json" \
  -d '{"name": "New aged care facility", "record_status": "proposal", "assigned_user": "1231"}'
```

{% tabs %}
{% tab title="200 The new record's id." %}

```javascript
{
    "id": "12345"
}
```

{% endtab %}

{% tab title="400 The record could not be created." %}

```javascript
{
    "error": "Insufficient permissions to add. - 23"
}
```

The message says what went wrong, followed by a code. Not having permission to add the record is also a `400`.
{% endtab %}
{% endtabs %}

## Update a record

<mark style="color:purple;">`PATCH`</mark> `https://api.tiny.plus/v2/{type}/{{id}}`

Send only the fields you want to change. `PUT` does the same thing.

```bash
curl -X PATCH "https://api.tiny.plus/v2/projects/{{id}}" \
  -H "Authorization: Bearer {{user_access_token}}" \
  -H "Content-Type: application/json" \
  -d '{"record_status": "won", "fee_value": "42000.00"}'
```

{% tabs %}
{% tab title="200 The change was saved." %}

```javascript
{
    "results": true
}
```

{% endtab %}

{% tab title="200 The change could not be saved." %}

```javascript
{
    "results": false
}
```

{% endtab %}

{% tab title="403 The token's user may not change this record." %}

```javascript
{
    "error": "You may not edit this record: it is not one you own or administer."
}
```

{% endtab %}

{% tab title="404 There is no such record." %}

```javascript
{
    "error": "Record not found."
}
```

{% endtab %}
{% endtabs %}

## Fields that are not editable

Some fields are worked out or kept by tiny+ itself, such as `record_url`, `id` and a company's relationship plan fields. If a create or an update sends one, tiny+ leaves it out, saves the rest, and names what it left out:

```json
{
    "results": true,
    "ignored_fields": ["record_url", "plan_count"]
}
```

So you can send a record back much as you read it. A create answers with `id` and `ignored_fields` in the same way. An update that sends nothing but such fields saves nothing, and answers `"results": false`.

## Delete a record

<mark style="color:red;">`DELETE`</mark> `https://api.tiny.plus/v2/{type}/{{id}}`

The record is marked as deleted rather than erased. Reading it afterwards returns `410`.

{% tabs %}
{% tab title="200 The record was deleted." %}

```javascript
{
    "results": true
}
```

`results` is `false` if the record could not be deleted.
{% endtab %}

{% tab title="403 The token's user may not delete this record." %}

```javascript
{
    "error": "You may not delete this record."
}
```

{% endtab %}

{% tab title="404 There is no such record." %}

```javascript
{
    "error": "Record not found."
}
```

{% endtab %}
{% endtabs %}

## Search

<mark style="color:blue;">`GET`</mark> `https://api.tiny.plus/v2/search/{type}?q={words}`

Finds records whose name, description or a few other key fields contain every word you search for, and returns a short summary of each. Results come newest first.

| Parameter | Description                                                                                          |
| --------- | ---------------------------------------------------------------------------------------------------- |
| `q`       | The words to search for. Put a phrase in double quotes to search for it whole.                       |
| `limit`   | How many results to return. There's no default and no maximum: without `limit`, you get every match. |
| `start`   | The offset of the first result to return.                                                            |

* Search ignores filters.
* Words of fewer than three letters, and common address words such as "street" and "road", are left out. If that leaves nothing to search for, every record matches.
* A search looks only at the type in the URL, and works for every type the API serves, [stages](/api/endpoints/projects.md#stages) included.
* On accounts that use stages, add `stages=1` to a project search to get one result per stage.
* A search of posts (`/v2/search/updates`) leaves out the posts a [search on `GET /v2/updates`](/api/endpoints/updates.md#the-news-feed-or-a-search) leaves out: posts tiny+ writes automatically, confidential notes, and posts on a confidential record the token's user can't open.

```bash
curl "https://api.tiny.plus/v2/search/projects?q=sydenham&limit=5" \
  -H "Authorization: Bearer {{user_access_token}}"
```

```javascript
{
    "total_records": 1,
    "returned_records": 1,
    "records": [
        {
            "id": "62365",
            "name": "Example refurbishment, Sydenham",
            "record_status": "proposal",
            "primary_company_name": "Example Builders",
            "hero_thumb_uri": "",
            "show_obscured": false,
            ...
        }
    ]
}
```

## Changing records quietly

Add `dont_track=1` to a create or update to make the change quietly:

* tiny+ doesn't run the account's automated actions for it;
* nobody is notified;
* the token's user isn't added to a new record's team;
* an update doesn't change the record's `modified_date` or `modified_user`.

This is meant for integrations that keep tiny+ in step with another system, where a change isn't news to anyone.

## Fields every record has

These fields are common to every record type. Each record type's page lists the fields particular to it.

| Field             | Label in tiny+  | Type           | Notes                                                                                                                                                                                                                                                  | Editable                |
| ----------------- | --------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------- |
| `assigned_user`   | Assigned To     | Team member id | The id of the team member the record is assigned to.                                                                                                                                                                                                   | Yes                     |
| `confidential`    | Confidential?   | Yes/no         | `1` makes the record confidential: see [Permissions and confidential records](/api/concepts/permissions.md#confidential-records).                                                                                                                      | Yes                     |
| `created_date`    | Created         | Date-time      | In UTC. Set when the record is created.                                                                                                                                                                                                                | Account admins only     |
| `created_user`    | Created by      | Team member id | The team member who created the record.                                                                                                                                                                                                                | Account admins only     |
| `description`     | Description     | Text           | Free text.                                                                                                                                                                                                                                             | Yes                     |
| `external_url`    | External Link   | URL or object  | A link to the record in another system. Send an object keyed by your app's name, such as `{"MyApp": "https://app.example.com/135"}`. It's merged with links other apps have set, so each app keeps its own. A plain URL is stored under the key `"0"`. | Yes                     |
| `flavour`         | Record type     | Record type    | The record type, such as `projects`.                                                                                                                                                                                                                   | No                      |
| `id`              |                 | Record id      | The record's id.                                                                                                                                                                                                                                       | No                      |
| `is_synced`       | Is Synced?      | Yes/no         | `1` if the record is kept in step with another system.                                                                                                                                                                                                 | Yes                     |
| `modified_date`   | Last modified   | Date-time      | In UTC. Set when the record changes.                                                                                                                                                                                                                   | Account admins only     |
| `modified_user`   | Modified by     | Team member id | The team member who last changed the record.                                                                                                                                                                                                           | Account admins only     |
| `name`            | Name            | Text           | Required. The record's name. Up to 200 characters.                                                                                                                                                                                                     | Yes                     |
| `primary_related` | Primary Related | Record id      | For a record that belongs to another one, such as a stage or a meeting, that record's id.                                                                                                                                                              | Yes                     |
| `record_phase`    | Current Phase   | Record id      | The phase within the status, on accounts that use phases. Set it through `record_status`: see [Statuses and phases](/api/concepts/record-types.md#statuses-and-phases).                                                                                | Through `record_status` |
| `record_status`   | Record Status   | Option         | The record's status. Each record type has its own: `GET /v2/record_status/{type}` lists them.                                                                                                                                                          | Yes                     |
| `record_url`      | Record URL      | URL            | The record's address in tiny+.                                                                                                                                                                                                                         | No                      |
| `remote_id`       | Remote ID       | Text           | The record's id in the system it's synced from. Up to 50 characters.                                                                                                                                                                                   | Yes                     |
| `sync_origin`     | Sync Origin     | Text           | The name of the system the record is synced from, shown to people in tiny+. Up to 100 characters.                                                                                                                                                      | Yes                     |

A record you read also comes with:

* `perm_edit` and `perm_delete`: whether the token's user may change or delete it. See [Permissions and confidential records](/api/concepts/permissions.md).
* `show_obscured`: `true` when a confidential record has been masked.
* `record_status_display`: the status as tiny+ shows it, with its phase.
* `{field}_name` for each field that holds another record's id, when you get one record.
* `hero_path_uri` and `hero_thumb_uri`: the record's image, when it has one.
* its custom fields, as `custom_{id}`, and its `tags`. See [Record types and your account's fields](/api/concepts/record-types.md).
* on lists, its `team`.
