Overview
Geni infers most of your document automatically. When you need to change the result (add a description, document a rate limit response, map a custom validation rule), register an extension throughGeni::configure() or the extensions config key.
Geni::configure()
Register extensions in a service provider’s boot() method:
app/Providers/AppServiceProvider.php
Each
with*() method accepts several arguments or a single array. Class names are resolved from the service container.
Per-API Registration
Geni::configure() targets the default API. Registrations for default also apply to every named API in geni.apis. Pass a name to target one API only:
v2 gets both changes, while the default document only gets the shared description.
For each API, extensions run in this order:
- Classes in
geni.extensions - Classes in
geni.apis.{name}.extensions Geni::configure()registrations fordefaultGeni::configure('{name}')registrations
Document Transformers
A document transformer changes the finished OpenAPI document of an API (info, servers, security, components, paths) before it is cached, served or exported.app/Docs/SetTermsOfService.php
fn (OpenApiDocument $document, string $apiName) => ....
Operation Transformers
An operation transformer changes one documented operation, with access to the route it came from.app/Docs/TagOperationsWithRouteName.php
DiscoveredRoute exposes uri, methods, action, middleware and name. Operation exposes properties such as summary, description, tags, operationId, deprecated, security, responses and extensions (keys emitted as top-level x-* properties of the operation).
Rule Transformers
Map custom validation rules (for exampleipv4_cidr, or a Rule object’s string form) to JSON Schema changes:
app/Docs/Ipv4CidrRule.php
'network' => ['required', 'ipv4_cidr'] is then documented as {"type": "string", "format": "ipv4-cidr"}.
Exception Responses
Map your own exceptions (declared with@throws) to HTTP status codes:
app/Docs/PaymentRequiredResponse.php
@throws PaymentRequiredException then documents a 402 response.
Registering Extensions in Config
Classes can also be listed inconfig/geni.php. Each class is registered by the interface(s) it implements (DocumentTransformer, OperationTransformer, RuleTransformer, ExceptionToResponse):
config/geni.php
Servers
geni.servers (or servers inside an entry of geni.apis) sets the OpenAPI servers list as description => URL:
config/geni.php
url(), so '/' becomes your app URL (for example http://localhost). Paths in the document stay absolute (for example /api/users), so point servers at the host, not at the API prefix.
Operation IDs
Every operation gets anoperationId, chosen in this order:
- An explicit id:
#[Endpoint(operationId: ...)]or@operationId. - The route name, without a leading
api.:api.users.indexbecomesusers.index. - The controller and method:
UserController@showbecomesuser.show. TheControllersuffix and theApp,Http,ApiandControllersnamespace parts are dropped, and the last two remaining parts are used. When that is not unique, the full controller path is used. - As a last resort, the id is made unique with a numeric suffix.
operationId.
A PATCH documented next to PUT on the same route (the update route of Route::apiResource(), or Route::match(['PUT', 'PATCH'], ...)) gets a _patch suffix:
Generated ids do not rename MCP tools in the default
snake naming mode. Set geni.mcp.tool_naming to operation_id to use them as tool names. See Tool Naming.