### Install Notra SDK using npm Source: https://docs.usenotra.com/api/getting-started Command to install the Notra SDK package using npm. ```bash npm install @usenotra/sdk ``` -------------------------------- ### Install MCP Server via add-mcp Source: https://docs.usenotra.com/integrations/mcp Use the add-mcp CLI tool to install the server with the required authorization header. ```bash npx add-mcp https://mcp.usenotra.com/mcp --header "Authorization: Bearer $TOKEN" ``` -------------------------------- ### Install Notra SDK using bun Source: https://docs.usenotra.com/api/getting-started Command to install the Notra SDK package using bun. ```bash bun add @usenotra/sdk ``` -------------------------------- ### Install Notra SDK using yarn Source: https://docs.usenotra.com/api/getting-started Command to install the Notra SDK package using yarn. ```bash yarn add @usenotra/sdk ``` -------------------------------- ### Install Notra SDK using pnpm Source: https://docs.usenotra.com/api/getting-started Command to install the Notra SDK package using pnpm. ```bash pnpm add @usenotra/sdk ``` -------------------------------- ### Success Response Example Source: https://docs.usenotra.com/api/pagination This is an example of a successful response from the API, containing a list of posts and pagination details. It includes information about the current page, total pages, and total items. ```json { "posts": [ { "id": "YOUR_POST_ID", "title": "February 12-19, 2026 Release", "content": "
This week brought meaningful improvements to organization management, scheduling, and mobile responsiveness.
Leave and delete operations now use consistent, validated server logic with atomic operations to prevent race conditions on concurrent requests.
", "markdown": "This week brought meaningful improvements to organization management, scheduling, and mobile responsiveness.\n\n## Highlights\n\n### Organization membership unification with server validation\nLeave and delete operations now use consistent, validated server logic with atomic operations to prevent race conditions on concurrent requests.", "contentType": "changelog", "sourceMetadata": null, "status": "published", "createdAt": "2026-02-19T11:32:54.082Z", "updatedAt": "2026-02-19T11:32:54.082Z" } ], "pagination": { "limit": 10, "currentPage": 1, "nextPage": null, "previousPage": null, "totalPages": 1, "totalItems": 1 } } ``` -------------------------------- ### Configure MCP Client Source: https://docs.usenotra.com/integrations/mcp Manual configuration examples for different MCP clients to connect to the Notra server. ```json "notra": { "type": "remote", "url": "https://mcp.usenotra.com/mcp", "enabled": true, "headers": { "Authorization": "Bearer YOUR_API_KEY" } } ``` ```json "notra": { "url": "https://mcp.usenotra.com/mcp", "headers": { "Authorization": "Bearer YOUR_API_KEY" } } ``` ```json "notra": { "type": "http", "url": "https://mcp.usenotra.com/mcp", "headers": { "Authorization": "Bearer YOUR_API_KEY" } } ``` -------------------------------- ### Empty Result Set Example Source: https://docs.usenotra.com/api/pagination This JSON example shows an empty result set, where no posts are returned. The pagination object correctly indicates zero total items and one total page. ```json { "posts": [], "pagination": { "limit": 10, "currentPage": 1, "nextPage": null, "previousPage": null, "totalPages": 1, "totalItems": 0 } } ``` -------------------------------- ### Initialize Notra Client Source: https://docs.usenotra.com/api/getting-started Example of initializing the Notra client with an API key. It's recommended to store the API key in an environment variable. ```typescript import { Notra } from "@usenotra/sdk"; const notra = new Notra({ bearerAuth: process.env.NOTRA_API_KEY ?? "", }); ``` -------------------------------- ### Initialize and List Posts with Notra TypeScript SDK Source: https://docs.usenotra.com/api/getting-started Demonstrates initializing the Notra SDK with an API key and fetching a list of posts. The API key should be stored securely, for example, in an environment variable. ```typescript import { Notra } from "@usenotra/sdk"; const notra = new Notra({ bearerAuth: process.env.NOTRA_API_KEY ?? "", }); const result = await notra.content.listPosts(); console.log(result.posts); ``` -------------------------------- ### Fetch Posts using cURL Source: https://docs.usenotra.com/api/getting-started Example of how to fetch a list of posts using cURL. Ensure you replace YOUR_API_KEY with your actual API key. ```bash curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.usenotra.com/v1/posts" ``` -------------------------------- ### GET /llms.txt Source: https://docs.usenotra.com/api-reference/content/update-a-single-brand-identity Retrieves the complete documentation index for the Notra API. ```APIDOC ## GET /llms.txt ### Description Fetch the complete documentation index to discover all available pages. ### Method GET ### Endpoint https://docs.usenotra.com/llms.txt ``` -------------------------------- ### GET /v1/posts Source: https://docs.usenotra.com/api/authentication Retrieves a list of posts using Bearer token authentication. ```APIDOC ## GET /v1/posts ### Description Retrieves a list of posts from the Notra platform. This endpoint requires a valid API key provided in the Authorization header. ### Method GET ### Endpoint https://api.usenotra.com/v1/posts ### Parameters #### Request Headers - **Authorization** (string) - Required - Bearer token (e.g., "Bearer YOUR_API_KEY") ### Response #### Success Response (200) - **data** (array) - A list of post objects. #### Error Response (401/403) - **error** (string) - Error message indicating missing or invalid API key. ``` -------------------------------- ### Authenticate API Requests Source: https://docs.usenotra.com/api/authentication Examples of how to include the Bearer token in API requests using cURL, the native fetch API, or the official Notra SDK. ```bash curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.usenotra.com/v1/posts" ``` ```typescript const response = await fetch("https://api.usenotra.com/v1/posts", { headers: { Authorization: `Bearer ${process.env.NOTRA_API_KEY}`, }, }); const data = await response.json(); console.log(data); ``` ```typescript import { Notra } from "@usenotra/sdk"; const notra = new Notra({ bearerAuth: process.env["NOTRA_BEARER_AUTH"] ?? "", }); const result = await notra.content.listPosts(); console.log(result); ``` -------------------------------- ### GET /v1/posts Source: https://docs.usenotra.com/api-reference/content/list-posts Retrieves a list of posts, with options to sort, paginate, and filter by status and content type. ```APIDOC ## GET /v1/posts ### Description Retrieves a list of posts. The organization is inferred from the API key. ### Method GET ### Endpoint /v1/posts ### Parameters #### Query Parameters - **sort** (string) - Optional - Sort by creation date. Enum: `asc`, `desc`. Default: `desc`. - **limit** (integer) - Optional - Items per page. Minimum: 1, Maximum: 100. Default: 10. - **page** (integer) - Optional - Page number. Minimum: 1. Default: 1. - **status** (string or array of strings) - Optional - Filter by status. Enum: `draft`, `published`. Can accept multiple values. - **contentType** (string or array of strings) - Optional - Filter by content type. Enum: `changelog`, `linkedin_post`, `twitter_post`, `blog_post`. Can accept multiple values. ### Response #### Success Response (200) - **organization** (object) - Information about the organization. - **id** (string) - **slug** (string) - **name** (string) - **logo** (string or null) - **posts** (array) - An array of post objects. - **id** (string) - **title** (string) - **slug** (string or null) - **content** (string) - **markdown** (string) - **recommendations** (string or null) - **contentType** (string) - **sourceMetadata** (object) - **status** (string) - Enum: `draft`, `published`. - **createdAt** (string) - **updatedAt** (string) #### Response Example ```json { "organization": { "id": "org_123", "slug": "my-org", "name": "My Organization", "logo": "https://example.com/logo.png" }, "posts": [ { "id": "post_abc", "title": "My First Post", "slug": "my-first-post", "content": "This is the content of my first post.
", "markdown": "This is the content of my first post.\n", "recommendations": null, "contentType": "blog_post", "sourceMetadata": {}, "status": "published", "createdAt": "2023-10-27T10:00:00Z", "updatedAt": "2023-10-27T10:00:00Z" } ] } ``` ``` -------------------------------- ### GET /v1/brand-identities Source: https://docs.usenotra.com/api-reference/content/list-available-brand-identities Retrieves a list of all brand identities associated with the authenticated organization. ```APIDOC ## GET /v1/brand-identities ### Description Fetches the list of available brand identities for the organization inferred from the provided API key. ### Method GET ### Endpoint /v1/brand-identities ### Response #### Success Response (200) - **organization** (object) - Details of the organization. - **brandIdentities** (array) - List of brand identity objects. #### Response Example { "organization": { "id": "org_123", "slug": "my-org", "name": "My Organization", "logo": "https://example.com/logo.png" }, "brandIdentities": [ { "id": "bi_456", "name": "Primary Brand", "isDefault": true, "websiteUrl": "https://brand.com", "companyName": "Brand Inc", "companyDescription": "Description", "toneProfile": "professional", "customTone": null, "customInstructions": null, "audience": "general", "language": "en", "createdAt": "2023-01-01T00:00:00Z", "updatedAt": "2023-01-01T00:00:00Z" } ] } ``` -------------------------------- ### Fetch a Single Post using Notra SDK Source: https://docs.usenotra.com/api/getting-started Example of fetching a specific post by its ID using the Notra SDK. Replace 'post_abc' with the actual post ID. ```typescript const post = await notra.content.getPost({ postId: "post_abc", }); ``` -------------------------------- ### GET /v1/posts - List Posts with Pagination Source: https://docs.usenotra.com/api/pagination This endpoint retrieves a list of posts and supports offset-based pagination. You can control the number of items per page and the specific page number to fetch. ```APIDOC ## GET /v1/posts ### Description Retrieves a list of posts with support for pagination. ### Method GET ### Endpoint /v1/posts ### Query Parameters - **limit** (integer) - Optional - The maximum number of items to return per page. Range: 1-100 items per page. Default: 10 - **page** (integer) - Optional - The page number to retrieve. Pages start at 1. Minimum: 1. Default: 1 ### Request Example ```bash cURL curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.usenotra.com/v1/posts?page=2&limit=5" ``` ### Response #### Success Response (200) - **pagination** (object) - Metadata about the current page and navigation options. - **limit** (integer) - The number of items requested per page (matches your query parameter). - **currentPage** (integer) - The current page number being returned. - **nextPage** (integer | null) - The next page number, or `null` if you're on the last page. - **previousPage** (integer | null) - The previous page number, or `null` if you're on the first page. - **totalPages** (integer) - The total number of pages available. - **totalItems** (integer) - The total number of items across all pages. #### Response Example ```json { "posts": [ { "id": "post_1", "title": "Example Post 1", "content": "This is the content of the first example post." }, { "id": "post_2", "title": "Example Post 2", "content": "This is the content of the second example post." } ], "pagination": { "limit": 5, "currentPage": 2, "nextPage": 3, "previousPage": 1, "totalPages": 10, "totalItems": 50 } } ``` ``` -------------------------------- ### GET /organizations/{organizationId}/posts Source: https://docs.usenotra.com/api-reference/content/list-posts Retrieves a list of posts for a specific organization, with support for pagination. ```APIDOC ## GET /organizations/{organizationId}/posts ### Description Retrieves a list of posts for a specific organization. Supports pagination to manage large datasets. ### Method GET ### Endpoint /organizations/{organizationId}/posts ### Parameters #### Path Parameters - **organizationId** (string) - Required - The unique identifier of the organization. #### Query Parameters - **limit** (integer) - Optional - The maximum number of posts to return per page. Minimum value is 1. - **currentPage** (integer) - Optional - The current page number to retrieve. Minimum value is 1. ### Response #### Success Response (200) - **organization** (object) - Details of the organization. - **id** (string) - The unique identifier of the organization. - **name** (string) - The name of the organization. - **posts** (array) - A list of posts. - **contentType** (string) - The content type of the post. - **status** (string) - The status of the post. - **createdAt** (string) - The timestamp when the post was created. - **updatedAt** (string) - The timestamp when the post was last updated. - **pagination** (object) - Pagination details for the response. - **limit** (integer) - The number of items per page. - **currentPage** (integer) - The current page number. - **nextPage** (integer | null) - The next page number, or null if on the last page. - **previousPage** (integer | null) - The previous page number, or null if on the first page. - **totalPages** (integer) - The total number of pages. - **totalItems** (integer) - The total number of items across all pages. #### Error Response (400) - **error** (string) - Description of the error (e.g., Invalid path params or query). #### Error Response (401) - **error** (string) - Description of the error (e.g., Missing or invalid API key). #### Error Response (403) - **error** (string) - Description of the error (e.g., Forbidden). #### Error Response (404) - **error** (string) - Description of the error (e.g., Organization not found). #### Error Response (503) - **error** (string) - Description of the error (e.g., Authentication service unavailable). ``` -------------------------------- ### Retrieve a single post via OpenAPI Source: https://docs.usenotra.com/api-reference/content/get-a-single-post Defines the OpenAPI schema for the GET /v1/posts/{postId} endpoint, requiring a Bearer token for authentication. ```yaml openapi: 3.1.1 info: title: Notra API version: 1.0.0 description: OpenAPI schema for authenticated content endpoints. servers: - url: https://api.usenotra.com description: Production security: - BearerAuth: [] tags: - name: Content description: >- Read content. Organization is inferred from the API key (identity.externalId). paths: /v1/posts/{postId}: get: tags: - Content summary: Get a single post operationId: getPost parameters: - schema: type: string minLength: 1 example: post_123 required: true in: path name: postId responses: '200': description: Post fetched successfully content: application/json: schema: type: object properties: organization: type: object properties: id: type: string slug: type: string name: type: string logo: type: - string - 'null' required: - id - slug - name - logo post: type: - object - 'null' properties: id: type: string title: type: string slug: type: - string - 'null' content: type: string markdown: type: string recommendations: type: - string - 'null' contentType: type: string sourceMetadata: {} status: type: string enum: - draft - published createdAt: type: string updatedAt: type: string required: - id - title - slug - content - markdown - recommendations - contentType - status - createdAt - updatedAt required: - organization - post '400': description: Invalid path params content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '401': description: Missing or invalid API key content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '403': description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Post or organization not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '503': description: Authentication service unavailable content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' components: schemas: ErrorResponse: type: object properties: error: type: string required: - error securitySchemes: BearerAuth: type: http scheme: bearer bearerFormat: API Key description: Send your API key in the Authorization header as Bearer API_KEY. ``` -------------------------------- ### GET /v1/brand-identities/generate/{jobId} Source: https://docs.usenotra.com/api-reference/content/get-async-brand-identity-generation-status Retrieves the current status and details of an asynchronous brand identity generation job. ```APIDOC ## GET /v1/brand-identities/generate/{jobId} ### Description Retrieves the status of an asynchronous brand identity generation job using the provided job ID. ### Method GET ### Endpoint /v1/brand-identities/generate/{jobId} ### Parameters #### Path Parameters - **jobId** (string) - Required - The unique identifier of the brand identity generation job. ### Response #### Success Response (200) - **organization** (object) - Details of the organization associated with the job. - **job** (object) - Details of the generation job, including status, progress, and timestamps. #### Response Example { "organization": { "id": "org_123", "slug": "my-org", "name": "My Organization", "logo": "https://example.com/logo.png" }, "job": { "id": "brand_job_123", "organizationId": "org_123", "brandIdentityId": "bi_456", "status": "completed", "step": "saving", "currentStep": 4, "totalSteps": 4, "workflowRunId": "run_789", "error": null, "createdAt": "2023-10-01T12:00:00Z", "updatedAt": "2023-10-01T12:05:00Z", "completedAt": "2023-10-01T12:05:00Z" } } ``` -------------------------------- ### Error Response - Invalid Page Source: https://docs.usenotra.com/api/pagination This JSON example illustrates an error response when an invalid page number is requested. It includes an error message and details about the requested page and total available pages. ```json { "error": "Invalid page number", "details": { "message": "Page 2 does not exist.", "totalPages": 1, "requestedPage": 2 } } ``` -------------------------------- ### GET /v1/posts/generate/{jobId} Source: https://docs.usenotra.com/api-reference/content/get-async-post-generation-status Retrieves the status of an asynchronous post generation job using its unique ID. ```APIDOC ## GET /v1/posts/generate/{jobId} ### Description Retrieves the status of an asynchronous post generation job. ### Method GET ### Endpoint /v1/posts/generate/{jobId} ### Parameters #### Path Parameters - **jobId** (string) - Required - The unique identifier for the post generation job. ### Responses #### Success Response (200) - **job** (object) - Contains details about the post generation job, including its ID, status, content type, and timestamps. - **id** (string) - The job ID. - **organizationId** (string) - The ID of the organization. - **status** (string) - The current status of the job (queued, running, completed, failed). - **contentType** (string) - The type of content being generated (changelog, blog_post, linkedin_post, twitter_post). - **lookbackWindow** (string) - The lookback window for content generation (current_day, yesterday, last_7_days, last_14_days, last_30_days). - **repositoryIds** (array) - A list of repository IDs used for generation. - **brandVoiceId** (string | null) - The ID of the brand voice used. - **workflowRunId** (string | null) - The ID of the workflow run. - **postId** (string | null) - The ID of the generated post. - **error** (string | null) - Any error message if the job failed. - **source** (string) - The source of the job (api, dashboard). - **createdAt** (string) - The timestamp when the job was created. - **updatedAt** (string) - The timestamp when the job was last updated. - **completedAt** (string | null) - The timestamp when the job was completed. - **events** (array) - A list of events associated with the job. - **id** (string) - The event ID. - **jobId** (string) - The ID of the job this event belongs to. - **type** (string) - The type of event (queued, workflow_triggered, running, fetching_repositories, generating_content, post_created, completed, failed). - **message** (string) - A message describing the event. - **createdAt** (string) - The timestamp when the event occurred. - **metadata** (object | null) - Additional metadata for the event. #### Response Example ```json { "job": { "id": "job_abc123", "organizationId": "org_xyz789", "status": "completed", "contentType": "blog_post", "lookbackWindow": "last_7_days", "repositoryIds": ["repo_1", "repo_2"], "brandVoiceId": "bv_456", "workflowRunId": "wr_789", "postId": "post_def456", "error": null, "source": "api", "createdAt": "2023-10-27T10:00:00Z", "updatedAt": "2023-10-27T10:05:00Z", "completedAt": "2023-10-27T10:05:00Z" }, "events": [ { "id": "event_1", "jobId": "job_abc123", "type": "queued", "message": "Job queued for processing.", "createdAt": "2023-10-27T10:00:00Z", "metadata": {} }, { "id": "event_2", "jobId": "job_abc123", "type": "completed", "message": "Post generation completed successfully.", "createdAt": "2023-10-27T10:05:00Z", "metadata": {} } ] } ``` ``` -------------------------------- ### Get a Single Post Source: https://docs.usenotra.com/api-reference/content/get-a-single-post Retrieves a specific post using its unique identifier. This endpoint is part of the Content API, which allows for reading content inferred from the API key. ```APIDOC ## GET /v1/posts/{postId} ### Description Retrieves a single post by its ID. The organization is inferred from the API key. ### Method GET ### Endpoint /v1/posts/{postId} ### Parameters #### Path Parameters - **postId** (string) - Required - The unique identifier of the post to retrieve. ### Request Example ```json { "example": "request body" } ``` ### Response #### Success Response (200) - **organization** (object) - Details of the organization associated with the post. - **id** (string) - The organization's ID. - **slug** (string) - The organization's slug. - **name** (string) - The organization's name. - **logo** (string | null) - The organization's logo URL. - **post** (object | null) - Details of the post. - **id** (string) - The post's ID. - **title** (string) - The post's title. - **slug** (string | null) - The post's slug. - **content** (string) - The post's content in HTML format. - **markdown** (string) - The post's content in Markdown format. - **recommendations** (string | null) - Recommendations related to the post. - **contentType** (string) - The type of content. - **sourceMetadata** ({}) - Metadata about the content source. - **status** (string) - The status of the post (e.g., 'draft', 'published'). - **createdAt** (string) - The timestamp when the post was created. - **updatedAt** (string) - The timestamp when the post was last updated. #### Response Example ```json { "organization": { "id": "org_abc123", "slug": "example-org", "name": "Example Organization", "logo": "https://example.com/logo.png" }, "post": { "id": "post_123", "title": "Example Post Title", "slug": "example-post", "content": "This is the HTML content.
", "markdown": "# Example Post Title\n\nThis is the Markdown content.", "recommendations": null, "contentType": "article", "sourceMetadata": {}, "status": "published", "createdAt": "2023-10-27T10:00:00Z", "updatedAt": "2023-10-27T10:00:00Z" } } ``` #### Error Responses - **400** - Invalid path parameters. - **401** - Missing or invalid API key. - **403** - Forbidden. - **404** - Post or organization not found. - **503** - Authentication service unavailable. ``` -------------------------------- ### Fetch API Data with Types Source: https://docs.usenotra.com/api/types Use these types when calling the Notra API directly with fetch. Ensure you handle JSON parsing and error responses appropriately. The API key should be securely managed, for example, using environment variables. ```typescript // 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(); ``` -------------------------------- ### Fetch First Page with Default Limit Source: https://docs.usenotra.com/api/pagination Use this to retrieve the first page of results with the default limit of 10 items. Requires an Authorization header. ```bash curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.usenotra.com/v1/posts" ``` ```typescript const result = await notra.content.listPosts(); ``` -------------------------------- ### List Posts with Pagination Source: https://docs.usenotra.com/api/pagination This section demonstrates how to fetch posts with pagination parameters and how to utilize the returned pagination object to determine navigation states. ```APIDOC ## GET /v1/posts ### Description Retrieves a list of posts with support for pagination. ### Method GET ### Endpoint /v1/posts ### Query Parameters - **page** (integer) - Optional - The page number to retrieve. - **limit** (integer) - Optional - The number of items per page. Defaults to 10. Values below 1 default to 1. Values above 100 are capped at 100. Non-numeric values default to 10. ### Request Example (Fetch API) ```typescript const response = await fetch( "https://api.usenotra.com/v1/posts?page=1&limit=10", { headers: { Authorization: `Bearer ${process.env.NOTRA_API_KEY}`, }, } ); const data = await response.json(); const { pagination } = data; const canGoBack = pagination.previousPage !== null; const canGoForward = pagination.nextPage !== null; const pageInfo = `Page ${pagination.currentPage} of ${pagination.totalPages}`; const itemCount = `${pagination.totalItems} total items`; ``` ### Request Example (SDK) ```typescript import type { Pagination } from "@usenotra/sdk/models/operations"; const result = await notra.content.listPosts({ page: 1, limit: 10, }); const { pagination } = result; const canGoBack = pagination.previousPage !== null; const canGoForward = pagination.nextPage !== null; const pageInfo = `Page ${pagination.currentPage} of ${pagination.totalPages}`; const itemCount = `${pagination.totalItems} total items`; ``` ### Response #### Success Response (200) - **posts** (array) - An array of post objects. - **pagination** (object) - An object containing pagination details. - **limit** (integer) - The number of items per page. - **currentPage** (integer) - The current page number. - **nextPage** (integer | null) - The next page number, or null if there is no next page. - **previousPage** (integer | null) - The previous page number, or null if there is no previous page. - **totalPages** (integer) - The total number of pages. - **totalItems** (integer) - The total number of items. #### Response Example (Success) ```json { "posts": [ { "id": "YOUR_POST_ID", "title": "February 12-19, 2026 Release", "content": "This week brought meaningful improvements to organization management, scheduling, and mobile responsiveness.
Leave and delete operations now use consistent, validated server logic with atomic operations to prevent race conditions on concurrent requests.
", "markdown": "This week brought meaningful improvements to organization management, scheduling, and mobile responsiveness.\n\n## Highlights\n\n### Organization membership unification with server validation\nLeave and delete operations now use consistent, validated server logic with atomic operations to prevent race conditions on concurrent requests.", "contentType": "changelog", "sourceMetadata": null, "status": "published", "createdAt": "2026-02-19T11:32:54.082Z", "updatedAt": "2026-02-19T11:32:54.082Z" } ], "pagination": { "limit": 10, "currentPage": 1, "nextPage": null, "previousPage": null, "totalPages": 1, "totalItems": 1 } } ``` #### Response Example (Empty Result Set) ```json { "posts": [], "pagination": { "limit": 10, "currentPage": 1, "nextPage": null, "previousPage": null, "totalPages": 1, "totalItems": 0 } } ``` ``` -------------------------------- ### Generate Cache Keys for Lists and Individual Posts Source: https://docs.usenotra.com/api/caching Demonstrates how to generate keys for both paginated list queries and specific individual post lookups. ```typescript const listKey = createPostsCacheKey({ page: 2, limit: 20, sort: "desc", status: ["published"], contentType: ["blog_post"], }); const postKey = ["notra", "post", "post_abc"] as const; ``` -------------------------------- ### Fetch Items with Custom Limit Source: https://docs.usenotra.com/api/pagination Use this to retrieve a specific number of items per page by setting the 'limit' query parameter. Requires an Authorization header. ```bash curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.usenotra.com/v1/posts?limit=5" ``` ```typescript const result = await notra.content.listPosts({ limit: 5, }); ``` -------------------------------- ### POST /v1/posts/generate Source: https://docs.usenotra.com/api-reference/content/queue-async-post-generation Queues an asynchronous post generation task based on provided content type, brand voice, and integration data. ```APIDOC ## POST /v1/posts/generate ### Description Queue an asynchronous post generation task. The organization is inferred from the provided API key. ### Method POST ### Endpoint /v1/posts/generate ### Request Body - **contentType** (string) - Required - Type of content to generate (changelog, blog_post, linkedin_post, twitter_post) - **lookbackWindow** (string) - Optional - Time window for data (current_day, yesterday, last_7_days, last_14_days, last_30_days) - **brandVoiceId** (string) - Required - ID of the brand voice to use - **brandIdentityId** (string) - Optional - ID of the brand identity - **repositoryIds** (array) - Optional - Deprecated list of repository IDs - **linearIntegrationIds** (array) - Optional - Deprecated list of Linear integration IDs - **integrations** (object) - Optional - Integration configuration containing github and linear arrays - **github** (object) - Optional - GitHub repository configuration - **dataPoints** (object) - Optional - Configuration for included data types (pullRequests, commits, releases, linearData) - **selectedItems** (object) - Optional - Specific items to include (commitShas, pullRequestNumbers) ### Request Example { "contentType": "blog_post", "brandVoiceId": "voice_123", "github": { "repositories": [ { "owner": "usenotra", "repo": "notra" } ] } } ``` -------------------------------- ### Fetch Data using Notra SDK and Extract Pagination Info Source: https://docs.usenotra.com/api/pagination This snippet demonstrates how to fetch paginated data using the Notra SDK. It shows how to access pagination information such as the current page, total pages, and total items. Make sure to import the Pagination type. ```typescript import type { Pagination } from "@usenotra/sdk/models/operations"; const result = await notra.content.listPosts({ page: 1, limit: 10, }); const { pagination } = result; const canGoBack = pagination.previousPage !== null; const canGoForward = pagination.nextPage !== null; const pageInfo = `Page ${pagination.currentPage} of ${pagination.totalPages}`; const itemCount = `${pagination.totalItems} total items`; ``` -------------------------------- ### GET /v1/brand-identities/{brandIdentityId} Source: https://docs.usenotra.com/api-reference/content/get-a-single-brand-identity Retrieves a specific brand identity by its unique identifier. This endpoint is part of the Content API and requires authentication via an API key. ```APIDOC ## GET /v1/brand-identities/{brandIdentityId} ### Description Retrieves a single brand identity using its ID. ### Method GET ### Endpoint https://api.usenotra.com/v1/brand-identities/{brandIdentityId} ### Parameters #### Path Parameters - **brandIdentityId** (string) - Required - The unique identifier for the brand identity. ### Request Body This endpoint does not accept a request body. ### Response #### Success Response (200) - **brandIdentity** (object) - Details of the brand identity. - **id** (string) - The brand identity's ID. - **name** (string) - The name of the brand identity. - **isDefault** (boolean) - Indicates if this is the default brand identity. - **websiteUrl** (string) - The website URL associated with the brand. - **companyName** (string | null) - The name of the company. - **companyDescription** (string | null) - A description of the company. - **toneProfile** (string | null) - The defined tone profile for the brand. - **customTone** (string | null) - Custom tone settings. - **customInstructions** (string | null) - Custom instructions for content generation. - **audience** (string | null) - The target audience for the brand. - **language** (string | null) - The primary language of the brand. - **createdAt** (string) - Timestamp of creation. - **updatedAt** (string) - Timestamp of last update. - **organization** (object) - Details of the organization. - **id** (string) - The organization's ID. - **slug** (string) - The organization's slug. - **name** (string) - The name of the organization. - **logo** (string | null) - URL of the organization's logo. #### Error Response (400) - **error** (string) - Description of the error (e.g., Invalid path params). #### Error Response (401) - **error** (string) - Description of the error (e.g., Missing or invalid API key). #### Error Response (403) - **error** (string) - Description of the error (e.g., Forbidden). #### Error Response (404) - **error** (string) - Description of the error (e.g., Organization not found). #### Error Response (503) - **error** (string) - Description of the error (e.g., Authentication service unavailable). ### Response Example (200) ```json { "brandIdentity": { "id": "51c2f3aa-efdd-4e28-8e69-23fa2dfd3561", "name": "Example Brand", "isDefault": true, "websiteUrl": "https://example.com", "companyName": "Example Corp", "companyDescription": "A leading provider of innovative solutions.", "toneProfile": "Professional", "customTone": "Friendly and approachable", "customInstructions": "Always use positive language.", "audience": "Tech enthusiasts", "language": "en", "createdAt": "2023-01-01T12:00:00Z", "updatedAt": "2023-01-01T12:00:00Z" }, "organization": { "id": "org-123", "slug": "example-org", "name": "Example Organization", "logo": "https://example.com/logo.png" } } ``` ### Response Example (400) ```json { "error": "Invalid brandIdentityId format." } ``` ``` -------------------------------- ### POST /v1/brand-identities/generate Source: https://docs.usenotra.com/api-reference/content/queue-async-brand-identity-generation Queues an asynchronous task to generate a brand identity for a specified website. ```APIDOC ## POST /v1/brand-identities/generate ### Description Queues an asynchronous brand identity generation process for a given website URL. ### Method POST ### Endpoint /v1/brand-identities/generate ### Request Body - **name** (string) - Optional - The name of the brand (1-120 characters). - **websiteUrl** (string) - Required - The URL of the website to generate the identity from. ### Request Example { "name": "Notra", "websiteUrl": "https://usenotra.com" } ### Response #### Success Response (202) - **organization** (object) - Details of the organization. - **job** (object) - Details of the background job, including status and progress. #### Response Example { "organization": { "id": "org_123", "slug": "notra", "name": "Notra", "logo": null }, "job": { "id": "job_456", "organizationId": "org_123", "brandIdentityId": "bi_789", "status": "queued", "step": null, "currentStep": 0, "totalSteps": 1, "workflowRunId": null, "error": null, "createdAt": "2023-10-27T10:00:00Z", "updatedAt": "2023-10-27T10:00:00Z", "completedAt": null } } ``` -------------------------------- ### List Available Integrations Source: https://docs.usenotra.com/api-reference/content/list-available-integrations Retrieve a list of all available integrations supported by Notra. This includes details for GitHub, Slack, and Linear integrations, as well as organization-specific information. ```APIDOC ## GET /v1/integrations ### Description Lists all available integrations for the authenticated user's organization. ### Method GET ### Endpoint /v1/integrations ### Parameters #### Query Parameters None ### Request Body None ### Request Example None ### Response #### Success Response (200) - **github** (array) - List of GitHub integrations. - **slack** (array) - List of Slack integrations. - **linear** (array) - List of Linear integrations. - **organization** (object) - Details about the organization. #### Response Example ```json { "github": [ { "id": "string", "displayName": "string", "owner": "string or null", "repo": "string or null", "defaultBranch": "string or null" } ], "slack": [], "linear": [ { "id": "string", "displayName": "string", "linearOrganizationId": "string", "linearOrganizationName": "string or null", "linearTeamId": "string or null", "linearTeamName": "string or null" } ], "organization": { "id": "string", "slug": "string", "name": "string", "logo": "string or null" } } ``` #### Error Response (401, 403, 404, 503) - **error** (string) - Description of the error. #### Error Response Example ```json { "error": "Missing or invalid API key" } ``` ```