Welcome to the Finch API Documentation and Swagger Guide! This guide will walk you through the steps to document your Finch application's API and integrate Swagger for interactive API documentation. Whether you're a seasoned developer or just starting, Finch offers a robust set of tools to simplify server-side web app development.

Defining API Documentation

Api documentation involved 3 main parts:

  • Adding Swagger to Routes
  • Adding ApiDoc route
  • Defining ApiDoc for each route

Finch provides a convenient way to document your API endpoints using the ApiDoc class. The ApiDoc class allows you to define the parameters, request body, and response structure for your API endpoints. Here's an example of how to use it:

Api documentation controller

final apiController = ApiController(
   title: "API Documentation",
   app: app,
);
// Routes that should be added to your FinchApp routing
// OpenApi json output
FinchRoute(
    key: 'root.api.docs',
    path: 'api/docs',
    index: apiController.indexPublic,
),
// Swagger UI
FinchRoute(
    key: 'root.swagger',
    path: 'swagger',
    index: () => apiController.swagger(rq.url('api/docs')),
),

Deffining ApiDoc for each route

class ApiDocuments {
    static Future<ApiDoc> onePerson() async {
    return ApiDoc(
      post: ApiDoc(
        response: {
          '200': [
            ApiResponse<int>('timestamp_start', def: 0),
            ApiResponse<bool>('success', def: true),
            ApiResponse<Map<String, String>>(
              'data',
              def: PersonCollectionFree.formPerson.fields.map((k, v) {
                return MapEntry(k, v.defaultValue?.call());
              }),
            ),
          ],
          '404': r_404,
        },
        description: "Update one person by id.",
        parameters: [
          ApiParameter<String>(
            'id',
            isRequired: true,
            paramIn: ParamIn.path,
          ),
          ApiParameter<String>(
            'name',
            isRequired: false,
            paramIn: ParamIn.header,
          ),
          ApiParameter<int>(
            'age',
            isRequired: false,
            paramIn: ParamIn.header,
          ),
          ApiParameter<double>(
            'height',
            isRequired: false,
            paramIn: ParamIn.header,
          ),
          ApiParameter<String>(
            'email',
            isRequired: true,
            paramIn: ParamIn.header,
          ),
          ApiParameter<String>(
            'married',
            isRequired: false,
            paramIn: ParamIn.header,
            def: false,
          ),
        ],
      ),
      get: ApiDoc(
        response: {
          '200': [
            ApiResponse<int>('timestamp_start', def: 0),
            ApiResponse<Map<String, String>>(
              'data',
              def: PersonCollectionFree.formPerson.fields.map((k, v) {
                return MapEntry(k, v.defaultValue?.call());
              }),
            ),
          ],
          '404': r_404,
        },
        description: "Get one person by id.",
        parameters: [
          ApiParameter<String>('id', isRequired: true, paramIn: ParamIn.path),
        ],
      ),
      delete: ApiDoc(
        response: {
          '200': [
            ApiResponse<int>('timestamp_start', def: 0),
            ApiResponse<bool>('success', def: true),
          ],
          '404': r_404,
        },
        description: "Delete one person by id.",
        parameters: [
          ApiParameter<String>('id', isRequired: true, paramIn: ParamIn.path),
        ],
      ),
    );
  }
}

/// Adding ApiDoc to Routes for example
FinchRoute(
  key: 'root.person.show',
  path: 'api/person/{id}',
  extraPath: ['example/person/{id}'],
  index: homeController.onePerson,
  methods: Methods.GET_POST,
  apiDoc: ApiDocuments.onePerson,
),