briefs
The methods of pd.briefs. Inputs and outputs are described in Conventions; every method can also fail as described in Errors.
Methods
pd.briefs.draft(input, init?)
Draft a content brief
POST /api/projects/{projectId}/brief
Asks the model for the angle, audience, search intent, keywords, reader questions, H2 headings, entities and a target length for one topic, fitted to the project's audience, and returns them without storing anything. Requires articles.create on the project. Costs no credits but counts against the ai_operations quota (429 QUOTA_EXCEEDED when used up). competitorTopics is never drafted: the model has no research to draw them from. To keep the brief send it to briefs.create; to write from it, copy its fields into the article's generationConfig.
Input
| Name | In | Type | Required | Description |
|---|---|---|---|---|
projectId |
path | string (uuid) |
yes | Id of the project. The workspace is read from the project, never from the request; a caller who is not a member of it gets 404 RESOURCE_NOT_FOUND. |
body |
body | object |
yes | |
body.topic |
body | string |
yes | The subject the brief is written for, 1 to 500 characters. |
body.primaryKeyword |
body | string |
no | A search phrase the brief must target, up to 200 characters. Absent: the model picks one. |
body.language |
body | string |
no | Language the brief is written in. Absent: the project's own language. |
init |
init | { signal?: AbortSignal; timeoutMs?: number } |
no | The second argument: signal aborts the call, timeoutMs overrides the client's per-attempt timeout. |
Returns 200 OK
| Field | Type | Required | Description |
|---|---|---|---|
brief |
object |
yes | The drafted brief. It is not stored and has no id; send it to briefs.create, with a title, to keep it. |
brief.angle |
string |
yes | The angle of the piece: what makes it worth reading. |
brief.audience |
string |
yes | Who the article is written for. |
brief.searchIntent |
"informational" | "commercial" | "transactional" | "navigational" |
yes | What the reader is looking for: informational (to learn), commercial (to compare options before choosing), transactional (to act or buy) or navigational (to reach a specific site or page). |
brief.primaryKeyword |
string |
yes | The main search phrase the article targets. |
brief.secondaryKeywords |
string[] |
yes | Supporting search phrases for the article. |
brief.questions |
string[] |
yes | Questions a reader arrives with that the article answers. |
brief.headings |
string[] |
yes | The H2 headings of the article, in reading order. |
brief.entities |
string[] |
yes | Products, concepts, standards and other named things the article mentions. |
brief.wordCount |
integer |
yes | Target length of the article in words, from 600 to 3000. |
Errors 400 invalid input, 401 missing or invalid key, 403 the key's roles lack the permission, 404 not found, 429 rate limited or out of quota. See Errors.
Example
import { PrismDraft } from "@prism-draft/sdk";
const pd = new PrismDraft({ apiKey: process.env.PRISMDRAFT_API_KEY! });
const result = await pd.briefs.draft({
projectId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
body: {
topic: "example",
},
});
console.log(result);
pd.briefs.list(input, init?)
List a project's stored briefs
GET /api/projects/{projectId}/briefs
Returns the briefs stored for the project, most recently updated first; the list is not paginated. Requires articles.read on the project.
Input
| Name | In | Type | Required | Description |
|---|---|---|---|---|
projectId |
path | string (uuid) |
yes | Id of the project. The workspace is read from the project, never from the request; a caller who is not a member of it gets 404 RESOURCE_NOT_FOUND. |
init |
init | { signal?: AbortSignal; timeoutMs?: number } |
no | The second argument: signal aborts the call, timeoutMs overrides the client's per-attempt timeout. |
Returns 200 OK
| Field | Type | Required | Description |
|---|---|---|---|
briefs |
object[] |
yes | The project's stored briefs, most recently updated first. Not paginated. |
briefs[].id |
string (uuid) |
yes | Id of the brief. |
briefs[].workspaceId |
string (uuid) |
yes | Id of the workspace that owns the brief. |
briefs[].projectId |
string (uuid) |
yes | Id of the project the brief belongs to. Fixed at creation; a brief never moves. |
briefs[].ideaId |
string (uuid) | null |
yes | Id of the idea the brief was written from. null when none was given, once it is unlinked (briefs.update with ideaId: null), or after the idea is deleted. |
briefs[].title |
string |
yes | Name the brief is filed under in the project's brief list; not an article title. |
briefs[].angle |
string |
yes | The take that makes the piece worth reading. |
briefs[].audience |
string |
yes | Who the article is written for. An empty string when not specified. |
briefs[].searchIntent |
"informational" | "commercial" | "transactional" | "navigational" |
yes | What the reader is looking for: informational (to learn), commercial (to compare options before choosing), transactional (to act or buy) or navigational (to reach a specific site or page). |
briefs[].primaryKeyword |
string |
yes | The main search phrase the article targets. An empty string when none. |
briefs[].secondaryKeywords |
string[] |
yes | Supporting search phrases. |
briefs[].questions |
string[] |
yes | Questions a reader arrives with and the article should answer. |
briefs[].headings |
string[] |
yes | The recommended H2 headings, in the order they should appear. |
briefs[].entities |
string[] |
yes | Products, concepts, standards and other named things the article should mention. |
briefs[].competitorTopics |
string[] |
yes | Topics that competing content covers, typed in by a person. The model never fills them, so they are empty unless someone entered them. |
briefs[].wordCount |
integer |
yes | Target length of the article in words. |
briefs[].createdBy |
string | null |
yes | Id of the user who stored the brief; for an API key, the user it acts for. null for a system actor or after that user is deleted. |
briefs[].createdAt |
string (date-time) |
yes | When the brief was stored, as an ISO 8601 UTC date-time. |
briefs[].updatedAt |
string (date-time) |
yes | When the brief was last changed, as an ISO 8601 UTC date-time. |
Errors 400 invalid input, 401 missing or invalid key, 403 the key's roles lack the permission, 404 not found, 429 rate limited or out of quota. See Errors.
Example
import { PrismDraft } from "@prism-draft/sdk";
const pd = new PrismDraft({ apiKey: process.env.PRISMDRAFT_API_KEY! });
const result = await pd.briefs.list({
projectId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);
pd.briefs.create(input, init?)
Store a content brief
POST /api/projects/{projectId}/briefs
Stores a brief for the project: the fields of a drafted brief (briefs.draft) plus a title and competitorTopics, which only a person types. Requires articles.create on the project (409 when it is archived). An ideaId, when given, must be an idea of this workspace (404 otherwise) that belongs to the same project or to none (400 otherwise). A stored brief is not read by article generation on its own: link an article to it with briefId on articles.create, and copy the fields you want into that article's generationConfig. Answers 201.
Input
| Name | In | Type | Required | Description |
|---|---|---|---|---|
projectId |
path | string (uuid) |
yes | Id of the project. The workspace is read from the project, never from the request; a caller who is not a member of it gets 404 RESOURCE_NOT_FOUND. |
body |
body | object |
yes | |
body.angle |
body | string |
yes | The angle of the piece: what makes it worth reading. |
body.audience |
body | string |
yes | Who the article is written for. Send an empty string when it is not specified. |
body.searchIntent |
body | "informational" | "commercial" | "transactional" | "navigational" |
yes | What the reader is looking for: informational (to learn), commercial (to compare options before choosing), transactional (to act or buy) or navigational (to reach a specific site or page). |
body.primaryKeyword |
body | string |
yes | The main search phrase the article targets. Send an empty string when there is none. |
body.secondaryKeywords |
body | string[] |
yes | Supporting search phrases for the article. |
body.questions |
body | string[] |
yes | Questions a reader arrives with that the article answers. |
body.headings |
body | string[] |
yes | The H2 headings of the article, in reading order. |
body.entities |
body | string[] |
yes | Products, concepts, standards and other named things the article mentions. |
body.wordCount |
body | integer |
yes | Target length of the article in words, from 600 to 3000. |
body.title |
body | string |
yes | Name the brief is filed under in the project's brief list; it is not the title of any article. |
body.competitorTopics |
body | string[] |
no | Topics that competing content covers, typed in by a person: at most 20, each up to 200 characters. The model never fills them, so a drafted brief has none. Default: []. |
body.ideaId |
body | string (uuid) |
no | Id of the idea (ideas.list) the brief was written from. It must be in this workspace and belong to the same project or to none (400 otherwise). Absent for a brief with no idea. |
init |
init | { signal?: AbortSignal; timeoutMs?: number } |
no | The second argument: signal aborts the call, timeoutMs overrides the client's per-attempt timeout. |
Returns 201 Created
| Field | Type | Required | Description |
|---|---|---|---|
brief |
object |
yes | The brief as stored after the request. |
brief.id |
string (uuid) |
yes | Id of the brief. |
brief.workspaceId |
string (uuid) |
yes | Id of the workspace that owns the brief. |
brief.projectId |
string (uuid) |
yes | Id of the project the brief belongs to. Fixed at creation; a brief never moves. |
brief.ideaId |
string (uuid) | null |
yes | Id of the idea the brief was written from. null when none was given, once it is unlinked (briefs.update with ideaId: null), or after the idea is deleted. |
brief.title |
string |
yes | Name the brief is filed under in the project's brief list; not an article title. |
brief.angle |
string |
yes | The take that makes the piece worth reading. |
brief.audience |
string |
yes | Who the article is written for. An empty string when not specified. |
brief.searchIntent |
"informational" | "commercial" | "transactional" | "navigational" |
yes | What the reader is looking for: informational (to learn), commercial (to compare options before choosing), transactional (to act or buy) or navigational (to reach a specific site or page). |
brief.primaryKeyword |
string |
yes | The main search phrase the article targets. An empty string when none. |
brief.secondaryKeywords |
string[] |
yes | Supporting search phrases. |
brief.questions |
string[] |
yes | Questions a reader arrives with and the article should answer. |
brief.headings |
string[] |
yes | The recommended H2 headings, in the order they should appear. |
brief.entities |
string[] |
yes | Products, concepts, standards and other named things the article should mention. |
brief.competitorTopics |
string[] |
yes | Topics that competing content covers, typed in by a person. The model never fills them, so they are empty unless someone entered them. |
brief.wordCount |
integer |
yes | Target length of the article in words. |
brief.createdBy |
string | null |
yes | Id of the user who stored the brief; for an API key, the user it acts for. null for a system actor or after that user is deleted. |
brief.createdAt |
string (date-time) |
yes | When the brief was stored, as an ISO 8601 UTC date-time. |
brief.updatedAt |
string (date-time) |
yes | When the brief was last changed, as an ISO 8601 UTC date-time. |
Errors 400 invalid input, 401 missing or invalid key, 403 the key's roles lack the permission, 404 not found, 429 rate limited or out of quota. See Errors.
Example
import { PrismDraft } from "@prism-draft/sdk";
const pd = new PrismDraft({ apiKey: process.env.PRISMDRAFT_API_KEY! });
const result = await pd.briefs.create({
projectId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
body: {
angle: "example",
audience: "example",
searchIntent: "informational",
primaryKeyword: "example",
secondaryKeywords: ["example"],
questions: ["example"],
headings: ["example"],
entities: ["example"],
wordCount: 600,
title: "example",
},
});
console.log(result);
pd.briefs.get(input, init?)
Read a stored brief
GET /api/briefs/{briefId}
Returns one stored brief. Requires articles.read on the brief's project; 404 when it does not exist or belongs to another workspace.
Input
| Name | In | Type | Required | Description |
|---|---|---|---|---|
briefId |
path | string (uuid) |
yes | Id of the stored brief. Its workspace and project are read from the brief; a caller who is not a member of that workspace gets 404 RESOURCE_NOT_FOUND, the same as for an unknown id. |
init |
init | { signal?: AbortSignal; timeoutMs?: number } |
no | The second argument: signal aborts the call, timeoutMs overrides the client's per-attempt timeout. |
Returns 200 OK
| Field | Type | Required | Description |
|---|---|---|---|
brief |
object |
yes | The brief as stored after the request. |
brief.id |
string (uuid) |
yes | Id of the brief. |
brief.workspaceId |
string (uuid) |
yes | Id of the workspace that owns the brief. |
brief.projectId |
string (uuid) |
yes | Id of the project the brief belongs to. Fixed at creation; a brief never moves. |
brief.ideaId |
string (uuid) | null |
yes | Id of the idea the brief was written from. null when none was given, once it is unlinked (briefs.update with ideaId: null), or after the idea is deleted. |
brief.title |
string |
yes | Name the brief is filed under in the project's brief list; not an article title. |
brief.angle |
string |
yes | The take that makes the piece worth reading. |
brief.audience |
string |
yes | Who the article is written for. An empty string when not specified. |
brief.searchIntent |
"informational" | "commercial" | "transactional" | "navigational" |
yes | What the reader is looking for: informational (to learn), commercial (to compare options before choosing), transactional (to act or buy) or navigational (to reach a specific site or page). |
brief.primaryKeyword |
string |
yes | The main search phrase the article targets. An empty string when none. |
brief.secondaryKeywords |
string[] |
yes | Supporting search phrases. |
brief.questions |
string[] |
yes | Questions a reader arrives with and the article should answer. |
brief.headings |
string[] |
yes | The recommended H2 headings, in the order they should appear. |
brief.entities |
string[] |
yes | Products, concepts, standards and other named things the article should mention. |
brief.competitorTopics |
string[] |
yes | Topics that competing content covers, typed in by a person. The model never fills them, so they are empty unless someone entered them. |
brief.wordCount |
integer |
yes | Target length of the article in words. |
brief.createdBy |
string | null |
yes | Id of the user who stored the brief; for an API key, the user it acts for. null for a system actor or after that user is deleted. |
brief.createdAt |
string (date-time) |
yes | When the brief was stored, as an ISO 8601 UTC date-time. |
brief.updatedAt |
string (date-time) |
yes | When the brief was last changed, as an ISO 8601 UTC date-time. |
Errors 400 invalid input, 401 missing or invalid key, 403 the key's roles lack the permission, 404 not found, 429 rate limited or out of quota. See Errors.
Example
import { PrismDraft } from "@prism-draft/sdk";
const pd = new PrismDraft({ apiKey: process.env.PRISMDRAFT_API_KEY! });
const result = await pd.briefs.get({
briefId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);
pd.briefs.update(input, init?)
Update a stored brief
PATCH /api/briefs/{briefId}
Changes the fields sent and keeps the others; a list sent replaces the stored list whole. Requires articles.update on the brief's project; 404 when it does not exist. The project cannot be changed: a brief is written again, not moved. ideaId follows the rules of briefs.create, and null unlinks the idea.
Input
| Name | In | Type | Required | Description |
|---|---|---|---|---|
briefId |
path | string (uuid) |
yes | Id of the stored brief. Its workspace and project are read from the brief; a caller who is not a member of that workspace gets 404 RESOURCE_NOT_FOUND, the same as for an unknown id. |
body |
body | object |
no | |
body.angle |
body | string |
no | The angle of the piece: what makes it worth reading. |
body.audience |
body | string |
no | Who the article is written for. Absent: unchanged. An empty string clears it. |
body.searchIntent |
body | "informational" | "commercial" | "transactional" | "navigational" |
no | What the reader is looking for: informational (to learn), commercial (to compare options before choosing), transactional (to act or buy) or navigational (to reach a specific site or page). |
body.primaryKeyword |
body | string |
no | The main search phrase the article targets. Absent: unchanged. An empty string clears it. |
body.secondaryKeywords |
body | string[] |
no | Supporting search phrases for the article. |
body.questions |
body | string[] |
no | Questions a reader arrives with that the article answers. |
body.headings |
body | string[] |
no | The H2 headings of the article, in reading order. |
body.entities |
body | string[] |
no | Products, concepts, standards and other named things the article mentions. |
body.wordCount |
body | integer |
no | Target length of the article in words, from 600 to 3000. |
body.title |
body | string |
no | Name the brief is filed under in the project's brief list; it is not the title of any article. |
body.competitorTopics |
body | string[] |
no | Topics that competing content covers, typed in by a person: at most 20, each up to 200 characters. The model never fills them, so a drafted brief has none. |
body.ideaId |
body | string (uuid) | null |
no | Id of the idea the brief was written from, under the same rules as on creation. null unlinks the idea; absent leaves the link as it is. |
init |
init | { signal?: AbortSignal; timeoutMs?: number } |
no | The second argument: signal aborts the call, timeoutMs overrides the client's per-attempt timeout. |
Returns 200 OK
| Field | Type | Required | Description |
|---|---|---|---|
brief |
object |
yes | The brief as stored after the request. |
brief.id |
string (uuid) |
yes | Id of the brief. |
brief.workspaceId |
string (uuid) |
yes | Id of the workspace that owns the brief. |
brief.projectId |
string (uuid) |
yes | Id of the project the brief belongs to. Fixed at creation; a brief never moves. |
brief.ideaId |
string (uuid) | null |
yes | Id of the idea the brief was written from. null when none was given, once it is unlinked (briefs.update with ideaId: null), or after the idea is deleted. |
brief.title |
string |
yes | Name the brief is filed under in the project's brief list; not an article title. |
brief.angle |
string |
yes | The take that makes the piece worth reading. |
brief.audience |
string |
yes | Who the article is written for. An empty string when not specified. |
brief.searchIntent |
"informational" | "commercial" | "transactional" | "navigational" |
yes | What the reader is looking for: informational (to learn), commercial (to compare options before choosing), transactional (to act or buy) or navigational (to reach a specific site or page). |
brief.primaryKeyword |
string |
yes | The main search phrase the article targets. An empty string when none. |
brief.secondaryKeywords |
string[] |
yes | Supporting search phrases. |
brief.questions |
string[] |
yes | Questions a reader arrives with and the article should answer. |
brief.headings |
string[] |
yes | The recommended H2 headings, in the order they should appear. |
brief.entities |
string[] |
yes | Products, concepts, standards and other named things the article should mention. |
brief.competitorTopics |
string[] |
yes | Topics that competing content covers, typed in by a person. The model never fills them, so they are empty unless someone entered them. |
brief.wordCount |
integer |
yes | Target length of the article in words. |
brief.createdBy |
string | null |
yes | Id of the user who stored the brief; for an API key, the user it acts for. null for a system actor or after that user is deleted. |
brief.createdAt |
string (date-time) |
yes | When the brief was stored, as an ISO 8601 UTC date-time. |
brief.updatedAt |
string (date-time) |
yes | When the brief was last changed, as an ISO 8601 UTC date-time. |
Errors 400 invalid input, 401 missing or invalid key, 403 the key's roles lack the permission, 404 not found, 429 rate limited or out of quota. See Errors.
Example
import { PrismDraft } from "@prism-draft/sdk";
const pd = new PrismDraft({ apiKey: process.env.PRISMDRAFT_API_KEY! });
const result = await pd.briefs.update({
briefId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);
pd.briefs.delete(input, init?)
Delete a stored brief
DELETE /api/briefs/{briefId}
Deletes the brief. Requires articles.delete on the brief's project; 404 when it does not exist. Articles written from the brief keep their content and lose the link: their briefId becomes null.
Input
| Name | In | Type | Required | Description |
|---|---|---|---|---|
briefId |
path | string (uuid) |
yes | Id of the stored brief. Its workspace and project are read from the brief; a caller who is not a member of that workspace gets 404 RESOURCE_NOT_FOUND, the same as for an unknown id. |
init |
init | { signal?: AbortSignal; timeoutMs?: number } |
no | The second argument: signal aborts the call, timeoutMs overrides the client's per-attempt timeout. |
Returns 200 OK
| Field | Type | Required | Description |
|---|---|---|---|
ok |
true |
yes | Always true. A resource that does not exist answers 404 instead. |
Errors 400 invalid input, 401 missing or invalid key, 403 the key's roles lack the permission, 404 not found, 429 rate limited or out of quota. See Errors.
Example
import { PrismDraft } from "@prism-draft/sdk";
const pd = new PrismDraft({ apiKey: process.env.PRISMDRAFT_API_KEY! });
const result = await pd.briefs.delete({
briefId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);