> For the complete documentation index, see [llms.txt](https://vladimirkostikov.gitbook.io/laraboom/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://vladimirkostikov.gitbook.io/laraboom/http/07-json-api.md).

# 7. JSON API /api

Every discovered Resource gets a REST like CRUD under the `boom` prefix, the `api` middleware group and `boom.*` route names.

## CRUD endpoints

| Method    | URI                    | Action  | Response                       |
| --------- | ---------------------- | ------- | ------------------------------ |
| GET       | `/api/{resource}`      | index   | a page (paginate 15) + present |
| POST      | `/api/{resource}`      | store   | 201 + present                  |
| GET       | `/api/{resource}/{id}` | show    | present                        |
| PUT/PATCH | `/api/{resource}/{id}` | update  | present                        |
| DELETE    | `/api/{resource}/{id}` | destroy | 204                            |

For Demo this is `/api/demos`.

## Lists. Filters and sorting

The engine is `ListQuery`.

A field filter. If the Field has `->filter()`:

```
GET /api/demos?status=active
GET /api/demos?featured=1
```

A filter method through `#[Filter('min_price')]`:

```
GET /api/demos?min_price=1000
```

Sorting works only for fields with `->sort()`:

```
GET /api/demos?sort=-price,name
```

A minus in front of the name means DESC. Without `sort` it is usually `latest(id)`.

Scopes (`#[Scope]`) are always applied. A client cannot turn them off.

## Present shape

The response is the result of `Resource::present($model)`:

* no secret fields
* for money the `price`, `price_amount`, `price_currency` fields
* for upload the `cover`, `cover_url` fields
* nested loaded relations

The index returns a Laravel paginator (data plus meta/links in the usual JSON).

## Permissions

Every action checks the `{resource}.{action}` Gate (`demos.index`, `demos.store` and so on). The rules are set by `#[Allow]` on the Resource.

An unauthorized JSON request to a protected action gets 401 or 403 in JSON. There will be no redirect to `/login`.

## Custom actions

Resource methods with `#[Get]`, `#[Post]` and other HTTP attributes:

```
GET  /api/demos/ping
POST /api/demos/echo
```

They also take `#[Throttle]`, `#[Check]`, `#[Allow]` and `only:`.

## Headers and middleware

Typical for the API group:

* JSON preference (`PreferJson` / Accept)
* `RequestId` on requests (it lands in the `note()` context)
* the idempotency alias for routes with `#[Idempotent]`

Idempotency works on Paths and actions. The `Idempotency-Key` header and the TTL from the attribute (86400 seconds by default). More in [chapter 10](/laraboom/http/10-http-guards.md).

## Create and update

The body of a POST or PATCH is JSON or a form with field keys. Validation is assembled from the Field rules. A secret is hashed. File fields accept an upload according to the rules.

A `Link` relation is written as an FK column (`parent_id`).

## Deletion

With softDeletes the row is hidden from `query()`. Whether a repeated show by id works depends on how CrudHandler looks the model up. Usually there is no trashed in the base query.

## OpenAPI

The spec is generated from resources, paths and `#[Check]`:

```bash
php boom openapi --out=openapi.json
```

See [chapter 14](/laraboom/quality/14-tooling.md).

## A practical scenario

```bash
# the list
curl -s 'http://127.0.0.1:8080/api/demos?status=active&sort=-price'

# create (if Allow store = true in Demo)
curl -s -X POST http://127.0.0.1:8080/api/demos \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -d '{"name":"Lin","email":"lin@demo.boom","password":"password","price":500,"stock":1,"status":"draft"}'

# ping
curl -s http://127.0.0.1:8080/api/demos/ping
```

## An example create response

After a successful `POST /api/demos` the host test expects fragments like:

```json
{
  "name": "New Kit",
  "price": 9900,
  "price_amount": "99.00",
  "price_currency": "RUB"
}
```

The `password` secret will not show up in the response body. Money returns both whole units and the formatted amount.

## Index pagination

`GET /api/demos` returns the standard Laravel paginator (usually 15 per page). The client pages through `?page=2`. The exact JSON meta depends on the paginator serialization version. Use the feature test and a live `getJson` response as the reference.

## Validation errors

An invalid store or update gives a 422 with field errors. The rules come from the Field (`needed`, `email`, `min`, the OneOf enum and so on).

## Custom actions and URI collisions

Do not name a custom `#[Get('...')]` in a way that unexpectedly intercepts `{id}`. A numeric id is show. String suffixes like `ping` and `echo` are registered as separate routes. When in doubt look at `php boom routes`.

## When not to use `/api`

* You need an HTML form with a session and CSRF. Take a Path.
* You need fully custom aggregate JSON (a dashboard). A Path or a `#[Get]` on the Resource with manual assembly.
* You need RPC without a model. A Path under `/api/...` (a uri with the `api` prefix).

For plain entity CRUD `/api` is the right default. Do not write a second controller just in case.

Next up is [Paths and Blade](/laraboom/http/08-paths.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://vladimirkostikov.gitbook.io/laraboom/http/07-json-api.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
