Skip to main content

Constructing API Requests

In this project, API requests are constructed using a structured configuration object defined by the ApiRequestOptions type. This approach decouples the definition of an API endpoint from the underlying execution logic (handled by Axios), allowing the generated SDK to describe requests declaratively.

The Request Blueprint: ApiRequestOptions

The ApiRequestOptions type in frontend/src/client/core/ApiRequestOptions.ts serves as the central interface for defining how a request should be built. Every service method in the generated SDK (e.g., ItemsService.readItems) creates an instance of this type and passes it to the core request function.

type ApiRequestOptions<T = unknown> = {
readonly method: 'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'PATCH' | 'POST' | 'PUT';
readonly url: string;
readonly path?: Record<string, unknown>;
readonly query?: Record<string, unknown>;
readonly body?: any;
readonly formData?: Record<string, unknown> | any[] | Blob | File;
readonly headers?: Record<string, unknown>;
readonly mediaType?: string;
readonly errors?: Record<number | string, string>;
// ... other specialized options
};

Dynamic Path Resolution

The url property often contains placeholders wrapped in curly braces, such as /api/v1/items/{id}. The core logic in frontend/src/client/core/request.ts uses the path property to resolve these placeholders.

When getUrl is called, it performs a regex replacement:

  1. It identifies placeholders like {id}.
  2. It looks up the corresponding key in the options.path object.
  3. It encodes the value and injects it into the URL.

Example from sdk.gen.ts:

public static updateItem(data: ItemsUpdateItemData): CancelablePromise<ItemsUpdateItemResponse> {
return __request(OpenAPI, {
method: 'PUT',
url: '/api/v1/items/{id}',
path: {
id: data.id // Resolves {id} in the URL
},
body: data.requestBody,
mediaType: 'application/json',
});
}

Query Parameters

Query parameters are defined via the query object. The getQueryString utility in request.ts recursively processes this object to build a standard URL query string, handling dates, arrays, and nested objects.

// Example: /api/v1/items/?skip=0&limit=10
public static readItems(data: ItemsReadItemsData = {}): CancelablePromise<ItemsReadItemsResponse> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/v1/items/',
query: {
skip: data.skip,
limit: data.limit
},
});
}

Request Payloads: Body vs. FormData

The project distinguishes between standard JSON payloads and multi-part form data:

  • body: Used for JSON payloads or raw Blobs. If mediaType is not specified, the system defaults to application/json for objects.
  • formData: Used for file uploads or application/x-www-form-urlencoded submissions. The getFormData helper automatically converts the formData record into a native FormData object.

Example of Form Data (Login):

public static loginAccessToken(data: LoginLoginAccessTokenData): CancelablePromise<LoginLoginAccessTokenResponse> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/v1/login/access-token',
formData: data.formData,
mediaType: 'application/x-www-form-urlencoded',
});
}

Headers and Media Types

The Headers type is a simple alias for Record<string, string>. Headers are resolved in a specific hierarchy in getHeaders:

  1. Global Headers: Defined in OpenAPI.HEADERS.
  2. Request Headers: Defined in options.headers.
  3. Authentication: If OpenAPI.TOKEN is present, an Authorization: Bearer <token> header is automatically added.
  4. Content-Type: Inferred from the mediaType property or the type of the body.

Custom Error Mapping

One of the most powerful features of ApiRequestOptions is the errors map. While the core logic provides default messages for standard HTTP status codes (e.g., 404: "Not Found"), individual requests can override these to provide domain-specific context.

errors: {
400: 'Custom bad request message for this specific endpoint',
422: 'Validation Error',
}

These mappings are processed by catchErrorCodes in request.ts, which throws an ApiError containing the mapped message if the response status matches a key in the errors object.