Custom endpoints
Applications and modules add endpoints for everything that is not a record of a resource, e.g. reports or imports. Authentication, rate limits, logging and the OpenAPI description come from Anvil.
use Anvil\Api\ApiEndpoint;use Anvil\Api\ApiEndpoints;use Anvil\Api\ApiRequest;use Anvil\Api\ApiResponse;
final class ReportApi implements ApiEndpoints{ public function endpoints(): array { return [ ApiEndpoint::get('reports/{uuid}') ->permission('reports.view') ->summary('One report') ->handle(fn (ApiRequest $request): ApiResponse => ApiResponse::ok(service('reports')->summary($request->parameter('uuid')))),
ApiEndpoint::post('reports/{uuid}/comments') ->permission('reports.comment') ->rules(['text' => ['required', 'string', 'max_length[2000]']]) ->idempotent() ->handle(function (ApiRequest $request): ApiResponse { $uuid = service('reports')->comment($request->parameter('uuid'), $request->string('text'));
return ApiResponse::created(['uuid' => (string) $uuid]); }), ]; }}- Paths are relative to
/api/v1/.{uuid}matches a UUID, other parameters ({serial}) one segment that the rules check. - Every endpoint needs a permission. Add own permissions to
$permissionsso they can be granted in the role editor and to clients. - Only fields with a rule reach the handler (path parameters, query and body). Invalid input is a 422.
- Writes (POST, PUT, PATCH, DELETE) run in a transaction and are audited
(
api.request). The body must be a JSON object of at most 1 MB. - Answers:
ApiResponse::ok($data),created($data, $location),page($list, $next),noContent(),withHeaders([...]); a handler may return an array, which is answered with 200. ThrowApiExceptionfor errors (notFound(),conflict(),validation([...]), …). Other exceptions are a generic 500 and logged with the request id. $request->clientis the calling client (ApiPrincipal): tenant, UUID, name, permissions. The tenant context, the gate and the audit actor are set to the client while the handler runs.rawInput()hands the unvalidated query and body to the handler ($request->query,$request->body), e.g. when the rules depend on the record. Validate them yourself.- The first endpoint of a path and method answers: custom endpoints come before resource endpoints.