Skip to content

OpenApiSpec and document metadata

The runtime document lives in an OpenApiSpec. Generated attachToApp methods fill it; you create it, set the metadata, and serve or serialise it.

Top-level OpenAPI 3.1 document.

class OpenApiSpec {
OpenApiSpec({
required ApiInfo info,
List<ApiServer> servers = const <ApiServer>[],
String openapi = '3.1.0',
Map<String, SecurityScheme>? securitySchemes,
Map<String, Object?>? extra,
});
}

When to use: create one per API (or per API version) at startup and pass it to every controller’s attachToApp. Several controllers can share one spec; their paths, schemas and tags are merged.

Parameter Type Default Description
info ApiInfo required Title, version and other metadata.
servers List<ApiServer> [] servers array. Omitted when empty.
openapi String '3.1.0' Value of the openapi field.
securitySchemes Map<String, SecurityScheme>? {'bearerAuth': SecurityScheme.bearer()} Schemes emitted under components.securitySchemes, and listed as alternatives on every guarded operation. Pass {} to leave security out. Emitted only when at least one operation is guarded.
extra Map<String, Object?>? {} Merged into the output last. Top-level keys replace generated ones, except components, which is merged section by section (an extra entry wins on a name clash).
Member Signature Description
paths Map<String, Map<String, Operation>> Path to lower-case method to Operation. Insertion order is kept, so output is stable.
putOperation void putOperation(String path, String method, Operation op) Adds or replaces an operation. method is lower-cased.
putSchema void putSchema(String name, Map<String, Object?> schema) Registers a component schema. The first registration of a name wins; later calls are no-ops.
hasSchema bool hasSchema(String name) Whether a component schema is registered.
putTag void putTag(String name, {String? description}) Adds a top-level tag, or sets its description if it had none.
toMap Map<String, Object?> toMap() The document as a plain map.
toJson String toJson({bool pretty = true}) The document as JSON, indented two spaces by default.

Example

import 'package:gisila_doc/gisila_doc.dart';
final spec = OpenApiSpec(
info: const ApiInfo(
title: 'My API',
version: '1.0.0',
description: 'Optional **Markdown**.',
contact: Contact(email: 'api@example.com'),
license: License(name: 'MIT', identifier: 'MIT'),
),
servers: const [
ApiServer(url: 'https://api.example.com', description: 'Production'),
],
extra: {
'externalDocs': {'url': 'https://example.com/guide'},
},
);
spec.putTag('Admin', description: 'Admin-only operations');
spec.putSchema('Money', {
'type': 'object',
'properties': {
'amount': {'type': 'integer'},
'currency': {'type': 'string'},
},
});
final json = spec.toJson();

See also: Generate API clients, Document authentication.

The info object.

class ApiInfo {
const ApiInfo({
required this.title,
required this.version,
this.description,
this.termsOfService,
this.contact,
this.license,
});
}

When to use: always; every spec needs one.

Parameter Type Default Description
title String required API name.
version String required Your API’s version (not the OpenAPI version).
description String? null Markdown description shown at the top of the docs.
termsOfService String? null URL.
contact Contact? null Contact information.
license License? null License information.

The info.contact object.

class Contact {
const Contact({this.name, this.url, this.email});
}

When to use: to tell API consumers whom to reach. All fields are optional; unset ones are omitted.

The info.license object.

class License {
const License({required this.name, this.identifier, this.url});
}

When to use: for public APIs. identifier is an SPDX expression (OpenAPI 3.1); use it or url, not both.

Parameter Type Default Description
name String required License name.
identifier String? null SPDX identifier, e.g. 'MIT'.
url String? null License URL.

One entry of servers.

class ApiServer {
const ApiServer({required this.url, this.description});
}

When to use: so “Try it out” in Swagger UI and generated clients target the right base URL. Without servers, Swagger UI uses the host serving the document.

An entry in components.securitySchemes.

class SecurityScheme {
const SecurityScheme({
required this.type,
this.scheme,
this.bearerFormat,
this.name,
this.location,
this.description,
});
const SecurityScheme.bearer({String bearerFormat = 'JWT', String? description});
const SecurityScheme.apiKey({
required String name,
String location = 'header',
String? description,
});
}

When to use: to describe how your gisila Authenticator reads credentials. The default spec already has bearerAuth (SecurityScheme.bearer()), matching gisila’s bearer and JWT authenticators. Add SecurityScheme.apiKey(name: 'X-API-Key') for ApiKeyAuthenticator.

Parameter Type Default Description
type String required ('http' / 'apiKey' in the named constructors) http, apiKey, oauth2, openIdConnect or mutualTLS.
scheme String? 'bearer' in .bearer For http: bearer, basic, …
bearerFormat String? 'JWT' in .bearer Hint shown in the docs.
name String? required in .apiKey Header, query or cookie name for apiKey.
location String? 'header' in .apiKey Emitted as in: header, query or cookie.
description String? null Description.

The class has no fields for OAuth flows or an OpenID Connect URL. For those, add the scheme through OpenApiSpec.extra['components'].

Example

final spec = OpenApiSpec(
info: const ApiInfo(title: 'My API', version: '1.0.0'),
securitySchemes: const {
'bearerAuth': SecurityScheme.bearer(),
'apiKey': SecurityScheme.apiKey(name: 'X-API-Key'),
'session': SecurityScheme.apiKey(name: 'sid', location: 'cookie'),
},
);

The JSON schema of gisila’s error body.

const Map<String, Object?> errorEnvelopeSchema = {
'type': 'object',
'properties': {
'error': {
'type': 'object',
'properties': {
'status': {'type': 'integer'},
'message': {'type': 'string'},
'code': {'type': 'string'},
'details': {'type': 'object'},
},
'required': ['status', 'message'],
},
},
'required': ['error'],
};

When to use: the generator uses it inline for automatic 400, 401 and 403 responses. Use it yourself when building operations by hand, or register it as a component: spec.putSchema('Error', errorEnvelopeSchema).