npm package: @financial-times/content-curation-client
Description: Client library for Content Curation API
Latest version: 5.3.0

# Content Curation API Client

TypeScript client library for interacting with the Content Curation API.

## Features

- Zod-validated request and response types
- Promise-based clients for homepage and page endpoints
- Typed transport, gateway, and service error handling
- Support for custom `fetch` implementations

## Installation

```bash
npm install @financial-times/content-curation-client
```

## API access

If you do not already have one, you can request an API Gateway key by completing the
[API Key Request Form](https://apigateway.in.ft.com/key-form).

## Usage

### Initialize the client

```typescript
import { ApiClient } from "@financial-times/content-curation-client";

const client = new ApiClient({
	baseUrl: "https://api-t.ft.com/content-curation",
	apiKey: "your-api-key",
});
```

### Get homepage structure

```typescript
const pageId = "123e4567-e89b-12d3-a456-426614174000";
const homepage = await client.homepage.getStructure(pageId);

console.log(homepage.properties.title);
```

### Get page structure

```typescript
const pageId = "123e4567-e89b-12d3-a456-426614174999";
const page = await client.page.getStructure(pageId);

console.log(page.properties.title);
```

### Update homepage structure

```typescript
import { HomepageStructureInput } from "@financial-times/content-curation-client";

const pageId = "58de2dc7-980b-4d51-8e45-9798f0c6b6bf";

const homepageStructure: Omit<HomepageStructureInput, "type"> = {
	properties: {
		pageId,
		homepageListId: "123e4567-e89b-12d3-a456-426614174000",
		title: "My Updated Homepage",
		publicationId: "homepage-publication-id",
	},
	children: [
		{
			type: "HomepageSlice",
			properties: {
				heading: {
					text: "Featured Section",
				},
			},
		},
	],
};

const homepage = await client.homepage.upsertStructure(pageId, homepageStructure);
```

### Update page structure

```typescript
import { PageStructureInput } from "@financial-times/content-curation-client";

const pageId = "123e4567-e89b-12d3-a456-426614174999";

const pageStructure: Omit<PageStructureInput, "type"> = {
	properties: {
		pageId,
		title: "My Updated Page",
		publicationId: "page-publication-id",
	},
	children: [
		{
			type: "HomepageSlice",
			properties: {
				heading: {
					text: "Featured Section",
				},
			},
		},
	],
};

const page = await client.page.upsertStructure(pageId, pageStructure);
```

## Error handling

Client methods throw `ApiClientError` for any client-generated failure. You can narrow that
base class into transport, gateway, and service errors when you need more specific handling.

```typescript
import {
	ApiClientError,
	ApiGatewayError,
	ApiServiceError,
	ApiTransportError,
} from "@financial-times/content-curation-client";

try {
	await client.page.getStructure("123e4567-e89b-12d3-a456-426614174999");
} catch (error) {
	if (error instanceof ApiTransportError) {
		console.error(error.transportKind, error.message, error.cause);
	} else if (error instanceof ApiGatewayError) {
		console.error(error.statusCode, error.contentType, error.bodyText);
	} else if (error instanceof ApiServiceError) {
		console.error(error.code, error.message, error.details);
	} else if (error instanceof ApiClientError) {
		console.error(error.origin, error.message);
	} else {
		throw error;
	}
}
```

### Error metadata

All `ApiClientError` instances expose:

- `origin`: `"transport" | "gateway" | "service"`
- `statusCode`: `0` for transport failures, otherwise the HTTP status code
- `requestId`: the upstream request identifier when available
- `url`: the request URL when available
- `contentType`: the response `content-type` when a response was received
- `bodyText`: truncated raw response text when the client captured it
- `cause`: the original thrown error for wrapped failures

`ApiTransportError` also exposes `transportKind`, and `ApiServiceError` is the subtype whose
`payload` is guaranteed to match the server-side `ApiErrorPayload` schema.

## Advanced usage

### Custom fetch implementation

You can provide your own `fetch` implementation for testing or integration with your own
runtime concerns:

```typescript
import { ApiClient } from "@financial-times/content-curation-client";

const client = new ApiClient({
	baseUrl: "https://api-t.ft.com/content-curation",
	apiKey: "your-api-key",
	fetch: customFetchFunction,
});
```

## Useful exported types

```typescript
import type {
	ApiErrorPayload,
	HomepageStructureInput,
	HomepageStructureOutput,
	PageDraft,
	PageStructureInput,
	PageStructureOutput,
} from "@financial-times/content-curation-client";
```