> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usenotra.com/llms.txt
> Use this file to discover all available pages before exploring further.

# TypeScript Types

> TypeScript type definitions for Notra API responses.

## Using the SDK

If you're using the `@usenotra/sdk` package, types are already included. Import them directly:

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
import type {
  GetPostPost,
  ListPostsPost,
  Pagination,
} from "@usenotra/sdk/models/operations";
```

<Tip>
  The SDK ships with full type definitions, so there is no need to maintain your own. The types below are only needed if you're calling the API with raw `fetch`.
</Tip>

***

## Using `fetch`

If you call the API directly with `fetch`, these types are a good starting point:

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
// Multiple posts
const listResponse = await fetch("https://api.usenotra.com/v1/posts", {
  headers: { Authorization: `Bearer ${process.env.NOTRA_API_KEY}` },
});
const listData: NotraPostListResponse = await listResponse.json();

// Single post
const postResponse = await fetch(
  "https://api.usenotra.com/v1/posts/YOUR_POST_ID",
  {
    headers: { Authorization: `Bearer ${process.env.NOTRA_API_KEY}` },
  }
);
const postData: NotraPostResponse = await postResponse.json();

// Updated post
const updateResponse = await fetch(
  "https://api.usenotra.com/v1/posts/YOUR_POST_ID",
  {
    method: "PATCH",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${process.env.NOTRA_API_KEY}`,
    },
    body: JSON.stringify({
      title: "Ship notes for week 11",
      markdown: "# Ship notes\n\nWe shipped a faster editor.",
      status: "published",
    }),
  }
);
const updateData: NotraPostUpdateResponse = await updateResponse.json();
```

### Type Definitions

Copy these types into your project:

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
export type Organization = {
  id: string;
  slug: string;
  name: string;
  logo: string | null;
};

export type Post = {
  id: string;
  title: string;
  slug: string | null;
  content: string;
  markdown: string;
  recommendations: string | null;
  contentType: string;
  sourceMetadata: unknown | null;
  status: "draft" | "published";
  createdAt: string;
  updatedAt: string;
};

export type Pagination = {
  limit: number;
  currentPage: number;
  nextPage: number | null;
  previousPage: number | null;
  totalPages: number;
  totalItems: number;
};

export type NotraPostListResponse = {
  organization: Organization;
  posts: Post[];
  pagination: Pagination;
};

export type NotraPostResponse = {
  organization: Organization;
  post: Post | null;
};

export type NotraPostUpdateRequest = {
  title?: string;
  slug?: string | null;
  markdown?: string;
  status?: "draft" | "published";
};

export type NotraPostUpdateResponse = {
  organization: Organization;
  post: Post;
};
```

<Tip>
  Copy these type definitions into a `types/notra.ts` file in your project.
</Tip>

### Zod Schemas

For runtime validation, you can use these Zod schemas:

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
import * as z from "zod";

export const OrganizationSchema = z.object({
  id: z.string(),
  slug: z.string(),
  name: z.string(),
  logo: z.string().nullable(),
});

export const PostSchema = z.object({
  id: z.string(),
  title: z.string(),
  slug: z.string().nullable(),
  content: z.string(),
  markdown: z.string(),
  recommendations: z.string().nullable(),
  contentType: z.string(),
  sourceMetadata: z.unknown().nullable(),
  status: z.enum(["draft", "published"]),
  createdAt: z.string(),
  updatedAt: z.string(),
});

export const PaginationSchema = z.object({
  limit: z.number().int().min(1),
  currentPage: z.number().int().min(1),
  nextPage: z.number().int().min(1).nullable(),
  previousPage: z.number().int().min(1).nullable(),
  totalPages: z.number().int().min(1),
  totalItems: z.number().int().min(0),
});

export const PostListResponseSchema = z.object({
  organization: OrganizationSchema,
  posts: z.array(PostSchema),
  pagination: PaginationSchema,
});

export const PostResponseSchema = z.object({
  organization: OrganizationSchema,
  post: PostSchema.nullable(),
});

const SLUG_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;

export const PostUpdateRequestSchema = z
  .object({
    title: z.string().trim().min(1).max(120).optional(),
    slug: z.string().trim().min(1).max(160).regex(SLUG_REGEX).nullable().optional(),
    markdown: z.string().min(1).max(100_000).optional(),
    status: z.enum(["draft", "published"]).optional(),
  })
  .refine(
    (data) =>
      data.title !== undefined ||
      data.slug !== undefined ||
      data.markdown !== undefined ||
      data.status !== undefined,
    { message: "At least one field must be provided" }
  );

export const PostUpdateResponseSchema = z.object({
  organization: OrganizationSchema,
  post: PostSchema,
});
```
