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.
Using the SDK
If you’re using the@usenotra/sdk package, types are already included. Import them directly:
import type {
GetPostPost,
ListPostsPost,
Pagination,
} from "@usenotra/sdk/models/operations";
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.Using fetch
If you call the API directly with fetch, these types are a good starting point:
// 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: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;
};
Copy these type definitions into a
types/notra.ts file in your project.Zod Schemas
For runtime validation, you can use these Zod schemas: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,
});