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

# Data API overview

> Read and write an app's records over HTTP — base URL, authentication, records, references, indexing, and errors.

The Data API reads and writes the records of an app's entities. The [JS SDK](https://docs.usehasp.com/app-builder/sdk/initialization.md) is a thin client over it; anything the SDK does, you can do over HTTP. Every endpoint is listed in the [Data API reference](#endpoints), generated from the platform's routes.

## Base URL

```
https://{org}.usehasp.run/api/hasp/v1/projects/{project}
```

`{org}` is your organization's runtime subdomain and `{project}` the project's slug. Records live under `/entities/{entity}/records`, where `{entity}` is the entity's slug.

## Authentication

| Caller | Credential | Header |
| - | - | - |
| A server or integration | Project API key, `hasp_pak_live_…` / `hasp_pak_test_…` | `Authorization: Bearer hasp_pak_live_…` |
| An AI agent acting for a user | Agent credential, `hasp_agt_live_…` / `hasp_agt_test_…` | `Authorization: Bearer hasp_agt_live_…` |
| The app itself, in the browser | The signed-in user's runtime session cookie | none — the SDK sends it same-origin |
| A visitor to a public app | none | `X-Hasp-AppId: <app id>` — reads of a `public` app's project, and anonymous form submissions where the app allows them |

Full details, including how each credential is scoped: [Authentication → Data API](https://docs.usehasp.com/ai-api/authentication.md#data-api).

### Creating a project API key

Open the project in the HASP platform and choose **API keys** in the project's sidebar. A project admin selects **New key**, names it, and picks **Live** or **Test**; the key's prefix (`hasp_pak_live_` / `hasp_pak_test_`) records that choice. The full key is shown once, right after it is created — copy it then, because HASP stores only a hash of it and cannot show it again. Every project member can see the key list (name, environment, last four characters, created and last-used dates, status); only project admins can create, rotate, or revoke keys.

* **Rotate** issues a replacement key immediately. The old key keeps working for 72 hours so an integration can switch over without downtime, then it is revoked automatically.
* **Revoke** takes effect immediately: the next request with that key fails with `API_KEY_REVOKED`.

A key reaches only the project it was created in. Issuing, rotating, and revoking a key are each recorded in the audit log.

## App-level endpoints

Two endpoints sit beside the project-scoped ones, at `https://{org}.usehasp.run/api/hasp/v1`, and are addressed by the `X-Hasp-AppId` header rather than a project:

* `GET /bootstrap` — the signed-in user, their org and app role, the app, and its Data API limits. Called with the runtime session; a `public` app also answers an anonymous caller. The SDK's `getBootstrap()`.
* `GET /status` — liveness, callable without credentials. With a project API key it also reports whether an app of the key's project is in maintenance. The SDK's `getStatus()`.

## Records

A record is the entity's declared fields plus three system fields:

```json theme={null}
{
  "id": "01JQ8Z6Y9V0M3T2R4S5K7W8XYZ",
  "name": "Ada Lovelace",
  "age": 36,
  "created_at": "2026-10-08T12:00:00+00:00",
  "updated_at": "2026-10-08T12:00:00+00:00"
}
```

The fields, their types, and their constraints come from the entity's schema, returned by `GET /projects/{project}/schema`. The published reference describes records as `EntityRecord`: the system fields plus `additionalProperties`, with an `x-hasp-entity-schema` extension pointing at that schema endpoint — the API spec cannot know your fields, the schema endpoint does.

Writes send field values under `data`. Keys that are not declared fields are dropped; values are validated against each field's type and constraints, and a failing field is reported in `error.details` under its key.

Numbers are stored exactly. A `number` or `currency` value that cannot be held exactly — an integer beyond 64 bits, or a decimal with more precision than a double carries — is rejected with `422` rather than rounded. Send large identifiers as `text`.

Bulk endpoints (`/records/bulk`) take up to 100 items and are **all-or-nothing**: every item is written in one transaction, or none is. A failing item is reported at its position — `records.3.title`, `updates.0.id`, `ids.2`.

## Filtering, sorting, and pagination

* `filter` — a JSON object of conditions. See [Filtering](https://docs.usehasp.com/app-builder/sdk/filtering.md) for the syntax and the operators each field type supports.
* `sort` — `field` or `field:asc|desc`, on `created_at`, `updated_at`, or any declared non-`json` field.
* `cursor` / `pageSize` — keyset pagination. See [Pagination](https://docs.usehasp.com/app-builder/sdk/pagination.md#how-cursors-behave).

A filter, sort, or cursor that cannot be applied exactly as written is rejected with `422`, never ignored.

## Indexing fields

Set `indexed: true` on a field (the `indexed` property on the AI API schema field endpoints, `POST /v1/projects/{project}/schemas/{entity}/fields` and `PATCH …/fields/{field}`, or `indexed: true` on a field in Studio's entity contract) and HASP builds a database index on it. Filters with `eq`, `gt`, `gte`, `lt`, `lte`, and `in`, and sorts on the field, are then served from the index instead of scanning the entity's records. `neq`, `contains`, and `starts_with` scan regardless.

* **Indexable types:** `number`, `currency`, `date`, `boolean`, `enum`, `reference`, `email`, and `phone` — types whose values are bounded. `text`, `multiline`, and `json` cannot be indexed; the schema API rejects `indexed: true` on them with `422`.
* **At most 10 indexed fields per entity.** Every index is maintained on every write, so index the fields you filter or sort on routinely — identifiers, statuses, dates — not every field.
* **At most 50 indexed fields per organization**, across all its projects.
* **String values of an indexed field are limited to 255 characters**, so they always fit in the index. Turning `indexed` on for a field that already holds a longer value is rejected with `422`; an indexed `enum`'s allowed values must fit too.

The index is built in the background after the schema change; until it exists, queries return the same results, just without the speed-up.

## References

A `reference` field holds the id of a record of another entity, and must declare which entity (`constraints.entity_slug`). When a record is written, each reference is checked: the target must exist, belong to the declared entity in the same project, and live in the **same environment** — a production record can only reference production records, and a sandbox record only records in its own sandbox.

References are checked when written, not maintained afterwards. If the referenced record is later deleted, the reference keeps its value; resolve it with a read and treat `404` as "no longer exists". An update that resends a reference unchanged is not re-checked, so a record whose target was deleted can still be edited.

## Errors

Every Data API error — on the app-level endpoints and for every credential type, agent credentials included — uses the same envelope as the AI API:

```json theme={null}
{
  "success": false,
  "error": {
    "type": "invalid_request",
    "code": "VALIDATION_FAILED",
    "message": "Cannot filter on 'ssn': it is not a declared field of this entity.",
    "param": "filter.ssn",
    "details": { "filter.ssn": ["Cannot filter on 'ssn': it is not a declared field of this entity."] },
    "retryable": false,
    "request_id": "01JQ…"
  },
  "meta": { "request_id": "01JQ…" }
}
```

Validation failures are `422 VALIDATION_FAILED` with every failing field in `error.details`, keyed by its path. The full code list is in [Errors](https://docs.usehasp.com/ai-api/reference/errors.md).

## Endpoints

The endpoint reference in this section is generated from the platform's routes into `openapi/data-v1.json` and checked for drift in CI.


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