# Documenting your API

To gather metadata about your API, we parse its source code in multiple passes. We call these passes strategies. A strategy is usually scoped to a specific aspect of your code: Documentation comments, attributes or OpenAPI annotations. Herodot ships with several built-in strategies that should cover most use cases. You can easily add your own strategies however, to make Herodot understand your domain specific code. See below to learn more about that.

# PHP Attributes

Extracts metadata by parsing well-defined attributes (opens new window). As attributes are a language construct with full support for type hints, named properties and so on, they are perfectly suited for documenting your API.

Attribute inheritance:
Attributes can also be set on controllers, causing them to be inherited by all of its methods. This makes it easy to share common attributes by adding them to a base class, or setting a group on controllers.

All attributes live in the Matchory\Herodot\Attributes namespace, but your IDE should autocomplete them anyway.

# Title

Adds a title to the endpoint. This attribute only has a single parameter for the title text. The title is intended to be used for single-line headings, and thus you should expect line breaks to be removed.

#[Title('Endpoint title')]

# Available arguments

Herodot accepts the following arguments to Title:

#[Title(
    title: 'Endpoint title',
)]
  • title
    Title text. This is required.

# Description

Adds a description to the endpoint. This attribute only has a single parameter for the description text. In contrary to the title, the description can take any length. All long-form text will be parsed as markdown (with HTML support) later on, just keep in mind that some output formats may not provide formatting options or do not support all of them.

#[Description("This is\na description text.")]

# Available arguments

Herodot accepts the following arguments to Description:

#[Description(
    description: 'An optional description',
)]
  • description
    Description text. This is required.

# Group

Adds the endpoint to a group. By default, all endpoints are in a group with an empty name, but by adding the Group attribute to an endpoint, you can move them into another group. This allows an easy way to add structure to your documentation, for example by grouping all user endpoints.
Endpoints may only be added to a single group. If you're looking for a way to tag endpoints instead, take a look at the Meta Attribute.

#[Group('Users')]

# Available arguments

Herodot accepts the following arguments to Group:

#[Group(
    name: 'Users',
    meta: [ 'key' => 'value' ]
)]
  • name
    Name of the group. This is required, and case-sensitive.
  • meta
    An array of key-value pairs with optional, non-standard metadata about the group. Metadata will be stored alongside the attribute and may be used differently depending on the output printer.

# Hidden

Marks the endpoint as hidden, subsequently omitting it from the documentation output--unless, that is, you use an output target that explicitly includes hidden routes (which may be useful for internal developer docs, for example).

#[Hidden]

# Available arguments

Herodot accepts the following arguments to Hidden:

#[Hidden(
    reason: 'An optional description',
)]
  • reason
    Optional reason why the endpoint is hidden. It may be shown in internal documentation only depending on the output printer.

# Internal

Marks the endpoint as internal. Internal endpoints should not be relied upon by end users, because they may be changed or removed at any time, but should still appear in your documentation for one reason or another.

#[Internal]

# Available arguments

Herodot accepts the following arguments to Internal:

#[Internal(
    description: 'An optional description',
    meta: [ 'key' => 'value' ]
)]
  • description
    An optional description on why this endpoint is internal. This will probably still be visible in the public documentation.
  • meta
    An array of key-value pairs with optional, non-standard metadata about the internal status. Metadata will be stored alongside the attribute and may be used differently depending on the output printer.

# Deprecated

Marks the endpoint as deprecated. Deprecated endpoints should not be used anymore and may be removed in a future version.

#[Deprecated]

# Available arguments

Herodot accepts the following arguments to Deprecated:

#[Deprecated(
    reason: 'Use the newer Users endpoint instead',
    version: '2.0.1',
    meta: [ 'key' => 'value' ]
)]
  • reason
    An optional reason why the endpoint is deprecated.
  • version
    An optional version since which this endpoint is deprecated. Herodot does not (yet) include actual support for API versions due to the complexity involved. We're all ears for your ideas, though!
  • meta
    An array of key-value pairs with optional, non-standard metadata about the deprecation status. Metadata will be stored alongside the attribute and may be used differently depending on the output printer.

# Authenticated

Marks the endpoint as requiring authentication. This attribute is the complement to the Unauthenticated attribute, they are mutually exclusive. You may optionally specify the guard handling the authentication.

#[Authenticated]

# Available arguments

Herodot accepts the following arguments to Authenticated:

#[Authenticated(
    guard: 'api'
)]
  • guard
    Name of the guard protecting the endpoint.

# Unauthenticated

Marks the endpoint as being publicly available. This attribute is the complement to the Authenticated attribute, they are mutually exclusive.

#[Unauthenticated]

# Available arguments

Herodot does not accept any arguments to Unauthenticated.

# Accepts

Adds an accepted media type to an endpoint, that is, a request body format your endpoint understands and is willing to parse. You may supply any media type to this attribute, even with wildcard expressions.

#[Accepts('image/*')]

# Available arguments

Herodot accepts the following arguments to Accepts:

#[Accepts(
    mediaType: 'image/png',
    description: 'Images in portable net graphics (PNG) format',
    meta: [ 'key' => 'value' ]
)]

The media type is the only required argument.

  • mediaType
    Name of the media type. This may be a valid media type according to the HTTP spec (opens new window), and accepts wildcards in both the type and the subtype (type/subtype).
  • description
    An optional description of the media type. You can use this to provide usage instructions.
  • meta
    An array of key-value pairs with optional, non-standard metadata about the media type. Metadata will be stored alongside the attribute and may be used differently depending on the output printer.

Adds a response header to an endpoint. This allows highlighting headers you use for a special purpose, or custom headers you use. Along with the (required) name of a header, and a description, you may supply an example of the value your API will respond with.

#[Header('X-Foo')]

# Available arguments

Herodot accepts the following arguments to Header:

#[Header(
    name: 'Content-Language',
    description: 'Language of the download file',
    example: 'English',
    meta: [ 'key' => 'value' ]
)]

The header name is the only required argument.

  • name
    Name of the header. As header names are case insensitive per the HTTP spec (opens new window), Herodot does ignore casing as well.
  • description
    An optional description of what or how you use the header. If it is a non-standard header, you should also describe the header itself.
  • example
    An optional example of a value your API might respond with.
  • meta
    An array of key-value pairs with optional, non-standard metadata about the header. Metadata will be stored alongside the attribute and may be used differently depending on the output printer.

# URL Parameters

Adds a URL parameter to an endpoint. URL Parameters, or dynamic segments in the URI of the endpoint, are usually represented as a placeholder in the URI: E.g. /foo/{bar}, where bar is a dynamic segment. Herodot merges all annotated URL parameter definitions with the actual parameters in the URI detected by the framework, to make sure no URL parameters go unnoticed.

#[UrlParam('id')]

Along with Query and Body parameters, URL parameters support a wide array of arguments. As you're probably mostly not going to use most of them at once, it is usually most convenient to use named arguments (opens new window):

#[UrlParam('id', description: 'ID of the record', deprecated: true)]

Using named arguments, you can selectively set the attributes relevant to your parameter.

# Available arguments

Herodot accepts the following arguments to UrlParam:

#[UrlParam(
    name: 'id',
    type: 'integer',
    description: 'ID of the record',
    required: true,
    default: null,
    example: 42,
    deprecated: true,
    validationRules: 'min:1',
    meta: [ 'key' => 'value' ]
)]

The parameter name is the only required argument.

  • name
    Name of the URL parameter. It must match the parameter as it occurs in the route, and is required.
  • type
    Type of the parameter. As URLs are usually only parsed as strings, there's not so much type information to extract. You should, however, use this to give a hint to users what data your API expects. If omitted, the type will default to string.
    Types are parsed using Herodot's type rules.
  • description
    An optional description of the parameter. The description may be as verbose as you like, and supports multi-line strings.
  • required
    Whether the parameter is required. Defaults to true.
  • default
    An optional default value for the parameter. Note that parameters with a default may not be required.
  • example
    An optional example of the expected parameter value.
  • deprecated
    Whether the parameter is deprecated and should not be used anymore. Defaults to false.
  • validationRules (beta)
    Hints on the applied constraints and validations enforced on this parameter. The concept for validation rules is not quite fleshed out yet due to the complexity involved.
  • meta
    An array of key-value pairs with optional, non-standard metadata about the parameter.

# Query Parameters

Adds a query parameter to an endpoint. Query parameters are part of the URL, and therefore generally only available as strings.

#[QueryParam('page')]

Along with URL and Body parameters, query parameters support a wide array of arguments. As you're probably mostly not going to use most of them at once, it is usually most convenient to use named arguments (opens new window):

#[QueryParam('page', description: 'Results page for the current query', default: 1)]

Using named arguments, you can selectively set the attributes relevant to your parameter.

# Available arguments

Herodot accepts the following arguments to QueryParam:

#[QueryParam(
    name: 'page',
    type: 'integer',
    description: 'Results page for the current query',
    required: false,
    default: 1,
    example: 42,
    deprecated: false,
    validationRules: 'min:1',
    meta: [ 'key' => 'value' ]
)]

The parameter name is the only required argument.

  • name
    Name of the query parameter.
  • type
    Type of the parameter. As URLs are usually only parsed as strings, there's not so much type information to extract. You should, however, use this to give a hint to users what data your API expects. If omitted, the type will default to string.
    Types are parsed using Herodot's type rules.
  • description
    An optional description of the parameter. The description may be as verbose as you like, and supports multi-line strings.
  • required
    Whether the parameter is required. Defaults to false.
  • default
    An optional default value for the parameter. Note that parameters with a default may not be required.
  • example
    An optional example of the expected parameter value.
  • deprecated
    Whether the parameter is deprecated and should not be used anymore. Defaults to false.
  • validationRules (beta)
    Hints on the applied constraints and validations enforced on this parameter. The concept for validation rules is not quite fleshed out yet due to the complexity involved.
  • meta
    An array of key-value pairs with optional, non-standard metadata about the parameter.

# Body Parameters

# Response

# ResponseFile

# Meta

Adds arbitrary metadata to an endpoint. This provides for a good way to extend Herodot in ways you see fit, without having to write an extension.

#[Meta('Key')]

You may optionally pass an arbitrary value (it's annotated as mixed):

#[Meta('Key', 'value')]

# OpenAPI Annotations

Extracts metadata by parsing OpenAPI annotations (opens new window).

# DocBlock comments

Extracts metadata by parsing docblock comments and analyzing a wide set of tags.

# Return Type Hints

Extracts metadata by parsing return types of route handlers to detect API resources (opens new window).

# Configuration Overrides

Extracts metadata by applying route overrides from the configuration file. The override strategy will typically supersede other strategies, allowing you to add manual overrides where necessary, for example for package routes you cannot influence.