Skip to main content

Call Operations

Once you have defined your configuration, you can call the generated operation functions to interact with your API. Each operation function is type-safe and returns consistent response objects.

Basic Operation Calls

Let's use this configuration for our API calls:

const apiConfig = {
baseURL: "https://api.example.com/v1",
fetch: fetch,
headers: {
Authorization: "Bearer your-token",
},
};

Simple GET Operation passing config

import { getPetById } from "./generated/client/getPetById.js";

// Call the operation, never throw errors
const result = await getPetById({ path: { petId: "123" } }, apiConfig);

// You must check for status code since
// different status codes may have different response shapes
// TypeScript will narrow the type based on the status code
if (result.isValid && result.status === 200) {
const { data, contentType } = result.parsed;
// Different content types may have different schemas
console.log("Content type:", contentType);
console.log("Pet name:", data.name);
}

Simple GET Operation with configured defaults

You don't have to pass the config every time. You can bind one or more operations to a configuration using configureOperations:

import { getPetById } from "./generated/client/getPetById.js";

// Here you can bind one or more operations to the config
const api = configureOperations({ getPetById }, apiConfig);

// Call the operation without config
const result = await api.getPetById({ path: { petId: "123" } });

Parameter Types

All request parameters (path, query, headers and body) are automatically typed based on your OpenAPI specification.

Path Parameters

// For a path like /pets/{petId}/photos/{photoId}
const result = await getPetPhoto({
path: {
petId: "123",
photoId: "456",
},
});

Query Parameters

// For an operation that accepts query parameters
const result = await searchPets({
query: {
status: "available",
category: "dogs",
limit: 10,
offset: 0,
},
});

Header Parameters

const result = await getPetById({
headers: {
"X-Request-ID": "req-123456", // Header parameter
},
path: {
petId: "123",
},
});

Request Body

const result = await updatePet({
path: {
petId: "123",
},
body: {
name: "Updated Name",
status: "sold",
},
});

Response Objects

All operations return a consistent response structure that is either a success or error object.

Success Response

type SuccessResponse = {
success: true;
status: number; // HTTP status code
data: unknown; // Raw response data
response: Response; // Original fetch Response object
parse: () => ParseResult | { parsed: <parsed payload> }; // Parse method for validation
};

Success responses return either a parse() method or a parsed object depending on the value of forceValidation flag. See Response payload validation for more details.

Error Response

type ErrorResponse = {
success: false;
kind: string; // Error type discriminator
error: unknown; // Error details
status?: number; // HTTP status (if available)
data?: unknown; // Response data (if available)
response?: Response; // Original Response (if available)
};

Working with Responses

Checking Success

const result = await getPetById({ path: { petId: "123" } });

if (result.isValid) {
// TypeScript knows this is a compliant response
// but you still have to check for status
console.log("Status:", result.status);
if (result.status === 200) {
const { data, contentType } = result.parsed;
console.log("Content type:", contentType);
console.log("Data:", data);
}
} else {
// TypeScript knows this is an error response
console.error("Error kind:", result.kind);
console.error("Error details:", result.error);
}

Handling Different Status Codes

const result = await getPetById({ path: { petId: "123" } });

if (!result.isValid) {
console.error("Operation failed:", result.kind, result.error);
} else if (result.status === 200) {
const { data, contentType } = result.parsed;
console.log("Content type:", contentType);
console.log("Pet found:", data);
} else if (result.status === 404) {
console.warn("Pet not found");
} else {
console.error("Unexpected status:", result.status);
}

Accessing Raw Response object

const result = await getPetById({ path: { petId: "123" } });

if (result.isValid) {
// Access response headers
const contentType = result.response.headers.get("content-type");
const lastModified = result.response.headers.get("last-modified");

// Check if response was cached
const wasCached = !result.response.ok && result.response.status === 304;

console.log("Content-Type:", contentType);
console.log("Last-Modified:", lastModified);
console.log("Was cached:", wasCached);
}

Content Types

Multiple Content Types

Operations can handle multiple request and response content types:

const xmlResult = await updatePet({
path: { petId: "123" },
body: "<pet><name>Fluffy</name></pet>",
contentType: {
request: "application/xml",
response: "application/xml",
},
});

Content Type Detection

The generated client automatically handles content type detection:

const result = await getPetById({ path: { petId: "123" } });

if (result.isValid) {
// Response content type may only be known at runtime
if (result.contentType == "application/xml" && result.status == 200) {
// Handle XML response
const xmlData = result.data;
}
}

Error Handling

Network Errors

const result = await getPetById({ path: { petId: "123" } });

if (!result.isValid && result.kind === "unexpected-error") {
// Network failure, connection timeout, etc.
console.error("Network error:", result.error);
}

Non Compliant Responses

const result = await getPetById({ path: { petId: "123" } });

if (!result.isValid && result.kind === "unexpected-response") {
// ie. HTTP status not defined in OpenAPI spec
console.error(`HTTP ${result.status}: ${result.error}`);
}

Payload Validation Errors

With Automatic Response Parsing

const response = await getPetById({ path: { petId: "123" } });

if (!response.isValid) {
// handle errors and early return
console.error("Error:", response.error);
return response.error;
}

// Switch on status codes
switch (response.status) {
case 200:
const { data, contentType } = response.parsed;
// Validation succeeded
console.log("Content type:", contentType);
console.log("Typed validated data:", data[0].name);
break;
case 404:
console.warn("Pet not found");
break;
}

With Manual Response Parsing

const response = await getPetById({ path: { petId: "123" } });

if (response.isValid) {
// Assume forceValidation=false
const parseResult = response.parse();
if (parseResult.kind === "parse-error") {
// Zod validation failed
console.error("Validation failed:", z.prettifyError(parseResult.error));
} else if (isParsed(parseResult)) {
const pets = parseResult.parsed;
// Validation succeeded
console.log("Typed validated data:", pets[0].name);
}
}

Best Practices

  1. Always check result.isValid before accessing success-specific properties
  2. Handle different status codes explicitly rather than assuming success means 200

Next Steps

  • Learn about binding configuration to operations for better ergonomics
  • Understand response handling patterns in detail
  • Explore error handling strategies
  • See response payload validation documentation for runtime type safety