Skip to content

Design

Designing an API means defining the contract of every resource interaction and organizing those contracts into an API Definition, API Groups, and API Endpoints. Each API Endpoint is fulfilled by an API Handler as a separate concern — owning the logic but not the contract.

API Definition (1)
└── API Group (1..N)
└── API Endpoint (1..N)
└── API Handler (1)

The API Definition serves as the source of truth, drives the generated OpenAPI specification, and enforces type safety across all API Handlers.

  1. Create an API Definition file:

    • Directoryapplications
      • Directorygateway
        • Directorysrc
          • Directoryapi
            • api.definition.ts
  2. Scaffold it based on the following snippet:

    import { HttpApi } from 'effect/unstable/httpapi';
    export const ApiDefinition = HttpApi.make('Api');

The API Group gathers API Endpoints that operate on related resources, keeping their contracts defined in one place.

  1. Locate the API Definition file:

    • Directoryapplications
      • Directorygateway
        • Directorysrc
          • Directoryapi
            • api.definition.ts
  2. Add an API Group based on the following snippet:

    import { HttpApi, HttpApiGroup } from 'effect/unstable/httpapi';
    const ApiGroupPlayers = HttpApiGroup.make('Players');
    export const ApiDefinition = HttpApi.make('Api').add(ApiGroupPlayers);

The API Endpoint defines the contract for a specific interaction with a resource.

  1. Locate the API Definition file:

    • Directoryapplications
      • Directorygateway
        • Directorysrc
          • Directoryapi
            • api.definition.ts
  2. Add an API Endpoint based on the following snippet:

    import { HttpApi, HttpApiEndpoint, HttpApiGroup } from 'effect/unstable/httpapi';
    const ApiGroupPlayers = HttpApiGroup.make('Players').add(
    HttpApiEndpoint.post('create-player', '/players'),
    );
    export const ApiDefinition = HttpApi.make('Api').add(ApiGroupPlayers);
  3. Extend the API Endpoint based on the following snippet:

    import {
    CreatePlayerError,
    CreatePlayerPayload,
    CreatePlayerRequestHeaders,
    CreatePlayerSuccess,
    } from '@applications/gateway/src/api/players/create-player.schema';
    import { HttpApi, HttpApiEndpoint, HttpApiGroup } from 'effect/unstable/httpapi';
    const ApiGroupPlayers = HttpApiGroup.make('Players').add(
    HttpApiEndpoint.post('create-player', '/players', {
    headers: CreatePlayerRequestHeaders,
    payload: CreatePlayerPayload,
    success: CreatePlayerSuccess,
    error: CreatePlayerError,
    }),
    );
    export const ApiDefinition = HttpApi.make('Api').add(ApiGroupPlayers);

The API Handler fulfills a single API Endpoint — receiving the declared input, executing the logic, and producing the declared output.

// TODO: Add implementation