# controller\_api

Source: https://zotonic.com/docs/1875/controller_api

URI: https://zotonic.com/id/1875

Language: en



`controller_api` exposes MQTT topics over HTTP at `/api/:topic`, including model calls. Requests use the normal MQTT and model access checks for the current user.

Model calls
-----------

The topic can refer to a model. In this case the topic pattern is one of:

- `/api/model/mymodel/get/foo/bar` maps to `m_mymodel:m_get([ <<"foo">>, <<"bar">> ], Msg, Context)`
- `/api/model/mymodel/post/foo/bar` maps to `m_mymodel:m_post([ <<"foo">>, <<"bar">> ], Msg, Context)`
- `/api/model/mymodel/delete/foo/bar` maps to `m_mymodel:m_delete([ <<"foo">>, <<"bar">> ], Msg, Context)`

In all cases, `Msg` is an MQTT message map, with the `payload` set to the body of the received request. In case of a GET, HEAD or DELETE the payload is set to a map of the query arguments.

Note that for a POST the payload might not be the complete message as additional query arguments are passed via `z_context:get_q(<<"argument_name">>, Context)`. If the model function is called using MQTT, then all arguments are contained in the payload.

HTTP methods
------------

| HTTP method | Supported topics                                              |
| ----------- | ------------------------------------------------------------- |
| GET         | Model `get` topics and non-model topics.                      |
| HEAD        | Model `get` topics only.                                      |
| POST        | Any topic, including model `get`, `post` and `delete` topics. |
| DELETE      | Model `delete` topics only.                                   |
| OPTIONS     | Any topic; does not call the model or publish a message.      |

A method/topic mismatch returns `400 Bad Request`. Known HTTP methods outside this list return `405 Method Not Allowed`; unrecognized methods return `501 Not Implemented`. The `Allow` header lists the controller's methods, rather than filtering them for the requested topic.

HEAD executes the model call and returns the same status and headers as GET, without a response body. It still performs authorization and model validation; it does not return success without checking the result. For example, to check whether all sites are running:

```sh
curl --head https://example.com/api/model/zotonic_status/get/check
```

On a site exposing the `zotonic_status` model, this returns `200 OK` when all sites are running, or `500 Internal Server Error` when the check fails.

Replies
-------

By default, the controller publishes a message to the topic and waits up to 60 seconds for its response. The response is encoded in the negotiated content type, with JSON as the default. Model errors determine the HTTP status, for example `403` for `eacces` and `404` for `enoent` or `unknown_path`.

With the `response_topic` query argument, the controller publishes the message and returns without waiting for the model's result. A non-empty value supplies the MQTT response topic; an empty value publishes without a response topic. The HTTP reply then reports the outcome of publishing, not the outcome of the model call.

HEAD rejects any `response_topic` query argument with `400 Bad Request`, including an empty value or a bare `?response_topic`. This ensures that HEAD waits for the model's result.

License: 

Attribution: 

Related resources: https://zotonic.com/api/agent/related/1875?language=en


## API access

- [API help](<https://zotonic.com/api-help>)
- [OpenAPI specification](<https://zotonic.com/openapi.json>)
- [This resource as JSON](<https://zotonic.com/api/agent/resource/1875?language=en>)
