ideas
The methods of pd.ideas. Inputs and outputs are described in Conventions; every method can also fail as described in Errors.
Methods
pd.ideas.list(input, init?)
List content ideas
GET /api/workspaces/{workspaceId}/ideas
Returns the workspace's content ideas ordered by priority (lowest number first), then newest first; the list is not paginated. Requires articles.read; with projectId, on that project (403 for a caller who is not one of its members; 404 RESOURCE_NOT_FOUND for a project that does not exist or belongs to another workspace), and without it the ideas of projects the caller cannot access are left out. An idea has no status of its own: it is open while its articleId is null and written once an article was created from it.
Input
| Name | In | Type | Required | Description |
|---|---|---|---|---|
workspaceId |
path | string (uuid) |
yes | Id of the workspace the request works in. The caller must be a member of it, or hold an API key issued by it. For anyone else, an unknown id and an id they do not belong to both answer 404 RESOURCE_NOT_FOUND, so membership cannot be probed. |
projectId |
query | string (uuid) |
no | Only the ideas planned for this project. Absent: every idea of the workspace, including workspace-level ones, which a project filter leaves out. |
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 |
|---|---|---|---|
ideas |
object[] |
yes | The ideas, ordered by priority (lowest number first), then newest first. Not paginated. |
ideas[].id |
string (uuid) |
yes | Id of the idea. |
ideas[].workspaceId |
string (uuid) |
yes | Id of the workspace that owns the idea. |
ideas[].projectId |
string (uuid) | null |
yes | Id of the project the idea is planned for. null for an idea that belongs to the workspace rather than to a project. |
ideas[].topic |
string |
yes | The subject to write about, in up to 300 characters. For a suggested idea (ideas.generate, or an onboarding draft) it equals title. |
ideas[].title |
string |
yes | Working headline for the article, up to 300 characters. An empty string when none was given. |
ideas[].primaryKeyword |
string |
yes | The main search phrase the idea targets. An empty string when none was given. |
ideas[].searchIntent |
"informational" | "commercial" | "transactional" | "navigational" | null |
yes | What a reader searching for this is after: informational (to learn), commercial (to compare options before choosing), transactional (to act or buy) or navigational (to reach a specific site or page). null when not set. |
ideas[].contentCluster |
string |
yes | Label of the group of related topics the idea belongs to, used to keep ideas on one theme together. An empty string when none was given. |
ideas[].priority |
integer |
yes | Rank from 1 (write first) to 5 (last). ideas.list returns lower numbers first; 3 when none was given. |
ideas[].articleId |
string (uuid) | null |
yes | Id of the article written from the idea. The server sets it when an article is created with this idea's ideaId (articles.create); it cannot be set here. null while the idea is open, and again if that article is deleted. |
ideas[].createdAt |
string (date-time) |
yes | When the idea was created, as an ISO 8601 UTC date-time. |
ideas[].updatedAt |
string (date-time) |
yes | When the idea 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.ideas.list({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);
pd.ideas.create(input, init?)
Create a content idea
POST /api/workspaces/{workspaceId}/ideas
Stores an idea by hand. Requires articles.create in the workspace, and on projectId when one is sent: a foreign project answers 404 and an archived one 409. An idea becomes an article through articles.create, which takes the idea's ideaId and sets its articleId; this call cannot set it. Answers 201.
Input
| Name | In | Type | Required | Description |
|---|---|---|---|---|
workspaceId |
path | string (uuid) |
yes | Id of the workspace the request works in. The caller must be a member of it, or hold an API key issued by it. For anyone else, an unknown id and an id they do not belong to both answer 404 RESOURCE_NOT_FOUND, so membership cannot be probed. |
body |
body | object |
yes | |
body.topic |
body | string |
yes | The subject to write about, 1 to 300 characters. Required on creation. |
body.title |
body | string |
no | A working headline for the article, up to 300 characters. Stored as an empty string when absent. |
body.primaryKeyword |
body | string |
no | The main search phrase the idea targets, up to 200 characters. Stored as an empty string when absent. |
body.searchIntent |
body | "informational" | "commercial" | "transactional" | "navigational" | null |
no | What a reader searching for this is after: informational (to learn), commercial (to compare options before choosing), transactional (to act or buy) or navigational (to reach a specific site or page). null or absent: not set. |
body.contentCluster |
body | string |
no | Label of the group of related topics the idea belongs to, up to 200 characters. Stored as an empty string when absent. |
body.priority |
body | integer |
no | Rank from 1 (write first) to 5 (last). Defaults to 3. |
body.projectId |
body | string (uuid) | null |
no | Id of the project the idea is planned for. It must be in this workspace (404 otherwise) and not archived (409), and the caller needs the permission on it. null or absent: a workspace-level 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 |
|---|---|---|---|
idea |
object |
yes | The idea as stored after the request. |
idea.id |
string (uuid) |
yes | Id of the idea. |
idea.workspaceId |
string (uuid) |
yes | Id of the workspace that owns the idea. |
idea.projectId |
string (uuid) | null |
yes | Id of the project the idea is planned for. null for an idea that belongs to the workspace rather than to a project. |
idea.topic |
string |
yes | The subject to write about, in up to 300 characters. For a suggested idea (ideas.generate, or an onboarding draft) it equals title. |
idea.title |
string |
yes | Working headline for the article, up to 300 characters. An empty string when none was given. |
idea.primaryKeyword |
string |
yes | The main search phrase the idea targets. An empty string when none was given. |
idea.searchIntent |
"informational" | "commercial" | "transactional" | "navigational" | null |
yes | What a reader searching for this is after: informational (to learn), commercial (to compare options before choosing), transactional (to act or buy) or navigational (to reach a specific site or page). null when not set. |
idea.contentCluster |
string |
yes | Label of the group of related topics the idea belongs to, used to keep ideas on one theme together. An empty string when none was given. |
idea.priority |
integer |
yes | Rank from 1 (write first) to 5 (last). ideas.list returns lower numbers first; 3 when none was given. |
idea.articleId |
string (uuid) | null |
yes | Id of the article written from the idea. The server sets it when an article is created with this idea's ideaId (articles.create); it cannot be set here. null while the idea is open, and again if that article is deleted. |
idea.createdAt |
string (date-time) |
yes | When the idea was created, as an ISO 8601 UTC date-time. |
idea.updatedAt |
string (date-time) |
yes | When the idea 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.ideas.create({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
body: {
topic: "example",
},
});
console.log(result);
pd.ideas.update(input, init?)
Update a content idea
PATCH /api/workspaces/{workspaceId}/ideas/{ideaId}
Changes the fields sent and keeps the others; null clears searchIntent and projectId. Requires articles.update, checked against the new projectId when one is sent and against the idea's current project and article: 403 for a caller who is not a member of a restricted project, 409 when that project is archived. 404 when the idea is not in the workspace. articleId cannot be changed here: only creating an article from the idea sets it.
Input
| Name | In | Type | Required | Description |
|---|---|---|---|---|
workspaceId |
path | string (uuid) |
yes | Id of the workspace the request works in. The caller must be a member of it, or hold an API key issued by it. For anyone else, an unknown id and an id they do not belong to both answer 404 RESOURCE_NOT_FOUND, so membership cannot be probed. |
ideaId |
path | string (uuid) |
yes | Id of the idea, in the workspace workspaceId. 404 when it is not. |
body |
body | object |
no | |
body.topic |
body | string |
no | The subject to write about, 1 to 300 characters. Absent: unchanged. |
body.title |
body | string |
no | A working headline for the article, up to 300 characters. Absent: unchanged. |
body.primaryKeyword |
body | string |
no | The main search phrase the idea targets, up to 200 characters. Absent: unchanged. |
body.searchIntent |
body | "informational" | "commercial" | "transactional" | "navigational" | null |
no | What a reader searching for this is after: informational (to learn), commercial (to compare options before choosing), transactional (to act or buy) or navigational (to reach a specific site or page). null clears it; absent: unchanged. |
body.contentCluster |
body | string |
no | Label of the group of related topics the idea belongs to, up to 200 characters. Absent: unchanged. |
body.priority |
body | integer |
no | Rank from 1 (write first) to 5 (last). Absent: unchanged. |
body.projectId |
body | string (uuid) | null |
no | Id of the project the idea is planned for, under the rules of ideas.create: in this workspace (404 otherwise), not archived (409), and the caller needs the permission on it. null makes it a workspace-level idea; absent: unchanged. |
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 |
|---|---|---|---|
idea |
object |
yes | The idea as stored after the request. |
idea.id |
string (uuid) |
yes | Id of the idea. |
idea.workspaceId |
string (uuid) |
yes | Id of the workspace that owns the idea. |
idea.projectId |
string (uuid) | null |
yes | Id of the project the idea is planned for. null for an idea that belongs to the workspace rather than to a project. |
idea.topic |
string |
yes | The subject to write about, in up to 300 characters. For a suggested idea (ideas.generate, or an onboarding draft) it equals title. |
idea.title |
string |
yes | Working headline for the article, up to 300 characters. An empty string when none was given. |
idea.primaryKeyword |
string |
yes | The main search phrase the idea targets. An empty string when none was given. |
idea.searchIntent |
"informational" | "commercial" | "transactional" | "navigational" | null |
yes | What a reader searching for this is after: informational (to learn), commercial (to compare options before choosing), transactional (to act or buy) or navigational (to reach a specific site or page). null when not set. |
idea.contentCluster |
string |
yes | Label of the group of related topics the idea belongs to, used to keep ideas on one theme together. An empty string when none was given. |
idea.priority |
integer |
yes | Rank from 1 (write first) to 5 (last). ideas.list returns lower numbers first; 3 when none was given. |
idea.articleId |
string (uuid) | null |
yes | Id of the article written from the idea. The server sets it when an article is created with this idea's ideaId (articles.create); it cannot be set here. null while the idea is open, and again if that article is deleted. |
idea.createdAt |
string (date-time) |
yes | When the idea was created, as an ISO 8601 UTC date-time. |
idea.updatedAt |
string (date-time) |
yes | When the idea 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.ideas.update({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
ideaId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);
pd.ideas.delete(input, init?)
Delete a content idea
DELETE /api/workspaces/{workspaceId}/ideas/{ideaId}
Deletes the idea. Requires articles.delete, on the idea's project and article when it has them (403 for a caller who is not a member of a restricted project, 409 when it is archived). An article written from it is untouched, and a stored brief that named it keeps its content and loses the link. 404 when the idea is not in the workspace.
Input
| Name | In | Type | Required | Description |
|---|---|---|---|---|
workspaceId |
path | string (uuid) |
yes | Id of the workspace the request works in. The caller must be a member of it, or hold an API key issued by it. For anyone else, an unknown id and an id they do not belong to both answer 404 RESOURCE_NOT_FOUND, so membership cannot be probed. |
ideaId |
path | string (uuid) |
yes | Id of the idea, in the workspace workspaceId. 404 when it is not. |
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.ideas.delete({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
ideaId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);
pd.ideas.generate(input, init?)
Suggest content ideas for a project
POST /api/projects/{projectId}/ideas/generate
Asks the model for up to 8 article ideas drawn from the project's profile (name, description, industry, audience, website and language) and stores them as ideas of the project with priority 3. The 60 most recent titles the project already has, as ideas or articles, are not repeated. Search volume and difficulty are never invented. Requires articles.create on the project. Costs 1 credit, reserved before the model is called, charged when at least one idea is stored, and released when none comes back or the call fails: 402 INSUFFICIENT_CREDITS when the balance cannot cover it, 429 QUOTA_EXCEEDED when the ai_operations quota is used up. Answers 201, with an empty ideas list when nothing new came back.
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 201 Created
| Field | Type | Required | Description |
|---|---|---|---|
ideas |
object[] |
yes | The ideas the model suggested and the server stored on the project, with priority 3 and no articleId. Empty when the batch brought nothing new. |
ideas[].id |
string (uuid) |
yes | Id of the idea. |
ideas[].workspaceId |
string (uuid) |
yes | Id of the workspace that owns the idea. |
ideas[].projectId |
string (uuid) | null |
yes | Id of the project the idea is planned for. null for an idea that belongs to the workspace rather than to a project. |
ideas[].topic |
string |
yes | The subject to write about, in up to 300 characters. For a suggested idea (ideas.generate, or an onboarding draft) it equals title. |
ideas[].title |
string |
yes | Working headline for the article, up to 300 characters. An empty string when none was given. |
ideas[].primaryKeyword |
string |
yes | The main search phrase the idea targets. An empty string when none was given. |
ideas[].searchIntent |
"informational" | "commercial" | "transactional" | "navigational" | null |
yes | What a reader searching for this is after: informational (to learn), commercial (to compare options before choosing), transactional (to act or buy) or navigational (to reach a specific site or page). null when not set. |
ideas[].contentCluster |
string |
yes | Label of the group of related topics the idea belongs to, used to keep ideas on one theme together. An empty string when none was given. |
ideas[].priority |
integer |
yes | Rank from 1 (write first) to 5 (last). ideas.list returns lower numbers first; 3 when none was given. |
ideas[].articleId |
string (uuid) | null |
yes | Id of the article written from the idea. The server sets it when an article is created with this idea's ideaId (articles.create); it cannot be set here. null while the idea is open, and again if that article is deleted. |
ideas[].createdAt |
string (date-time) |
yes | When the idea was created, as an ISO 8601 UTC date-time. |
ideas[].updatedAt |
string (date-time) |
yes | When the idea was last changed, as an ISO 8601 UTC date-time. |
credits |
integer |
yes | Credits charged for the batch: 1, or 0 when no idea came back. |
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.ideas.generate({
projectId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);