projects
The methods of pd.projects. Inputs and outputs are described in Conventions; every method can also fail as described in Errors.
Methods
pd.projects.list(input, init?)
List a workspace's projects
GET /api/workspaces/{workspaceId}/projects
Needs projects.read in the workspace. Newest first. Archived projects are left out unless includeArchived=true. A project that has members is listed only to them, and to a caller who holds projects.members.manage in the workspace, who administers it; a project with no members is listed to everyone. A member whose project role does not grant projects.read does not see the project either. An API key has no project membership, so it lists the open projects, and the restricted ones too when its role holds projects.members.manage. A platform administrator reading a workspace they do not belong to sees every project. A project left out of the list answers 403 when opened; one listed only because the caller manages members is likewise refused on read until they are a member, but its members can still be managed.
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. |
includeArchived |
query | string |
no | true to list archived projects too (see status on each). Defaults to false: only active projects. Accepts true/false, 1/0, yes/no, on/off. |
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 |
|---|---|---|---|
projects |
object[] |
yes | The workspace's projects, newest first; archived ones only with includeArchived. |
projects[].id |
string (uuid) |
yes | Id of the project, used in every /projects/{projectId} route. |
projects[].workspaceId |
string (uuid) |
yes | Id of the workspace that owns the project. |
projects[].name |
string |
yes | Display name of the project, 1 to 120 characters. |
projects[].slug |
string |
yes | URL-safe identifier, unique within the workspace. Generated from name when not sent at creation, and never changed afterwards. |
projects[].description |
string |
yes | Free-text description of the project, up to 2000 characters; empty when unset. |
projects[].settings |
Record<string, unknown> |
yes | The stored settings object, with the keys exactly as they were sent. The only key the server reads is images (image-generation settings); imageSettings is that key with its defaults filled in. |
projects[].websiteUrl |
string | null |
yes | Address of the website the project writes for; null when none was given. |
projects[].iconUrl |
string | null |
yes | Address of the site's icon, copied to the media host: found by the website analysis, or fetched when websiteUrl is set or changed and by POST .../icon/refresh. null until one is found. No request sets it directly. |
projects[].industry |
string |
yes | Free-text industry of the site, up to 200 characters; empty when unset. |
projects[].audience |
string |
yes | Free-text description of who the articles are written for, up to 500 characters; empty when unset. The app starts a new article's audience from it. |
projects[].language |
string |
yes | The project's default language, a language tag such as en or pt-BR: where a new article starts. Always one of languages. |
projects[].languages |
string[] |
yes | Every language the project publishes in, as language tags, with the default language first. Articles are written in one of these. |
projects[].defaultTone |
string |
yes | Tone a new article starts from, one of professional, conversational, authoritative, practical, persuasive. Each article can change it. |
projects[].defaultWordCount |
integer |
yes | Target length in words a new article starts from, from 200 to 10000. Each article can change it. |
projects[].status |
"active" | "archived" |
yes | active, or archived: read-only until POST /api/workspaces/{workspaceId}/projects/{projectId}/restore makes it active again. |
projects[].createdAt |
string (date-time) |
yes | When the project was created, as an ISO 8601 timestamp. |
projects[].updatedAt |
string (date-time) |
yes | When the project row last changed (an update, an archive or a restore), as an ISO 8601 timestamp. |
projects[].imageSettings |
object |
yes | The project's image-generation settings as generation uses them: settings.images with every default filled in. A stored value that no longer validates reads as the defaults. |
projects[].imageSettings.styleDescription |
string | null |
yes | The project's style description, appended to every image prompt; null when none is set. |
projects[].imageSettings.neverDepict |
string[] |
yes | The subjects no image may show, in force: the project's own list, or the default list (official documents, seals and emblems, flags, identifiable real people) when it has none. Empty when the project excluded nothing. |
projects[].imageSettings.hero |
object |
yes | Cover (hero) image settings, defaults filled in. |
projects[].imageSettings.hero.style |
"photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" | null |
yes | Style for cover images; null when unset, in which case the article's imageStyle applies. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
projects[].imageSettings.hero.aspect |
"16:9" | "1200x630" |
yes | Shape of cover images: 16:9 or 1200x630 (the social-card size). |
projects[].imageSettings.hero.prompt |
string | null |
yes | Standing direction for cover images; null when none is set. |
projects[].imageSettings.inline |
object |
yes | Inline image settings, defaults filled in. |
projects[].imageSettings.inline.style |
"photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" | null |
yes | Style for inline images; null when unset, in which case the article's imageStyle applies. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
projects[].imageSettings.inline.aspect |
"4:3" | "1:1" |
yes | Shape of inline images: 4:3 or 1:1. |
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.projects.list({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);
pd.projects.create(input, init?)
Create a project
POST /api/workspaces/{workspaceId}/projects
Needs projects.create. Creates an active project with no members, so it is open to every workspace member who holds the permissions. Counts against the workspace's projects quota: 429 QUOTA_EXCEEDED when the plan's limit is reached. Records a projects.created audit entry and answers 201. With a websiteUrl, queues a fetch of the site's icon.
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.name |
body | string |
yes | Display name of the project, 1 to 120 characters. Required to create one. |
body.slug |
body | string |
no | Wanted URL slug, 1 to 120 characters, normalised to lowercase words joined by hyphens. Taken from name when omitted. When another project of the workspace already has it, a short random suffix is appended. Cannot be changed afterwards, so an update does not accept it. |
body.description |
body | string |
no | Free-text description of the project, up to 2000 characters. Empty when omitted on create; unchanged when omitted on update. |
body.settings |
body | object |
no | Free-form settings object; any keys are stored as sent. Only images (image-generation settings) is read by the server, and it is validated. On create, omitted means {}. On update the keys sent replace the stored keys of the same name (images is replaced as a whole, not merged field by field) and keys not sent are kept. |
body.settings.images |
body | object |
no | The project's image settings. On update this replaces the stored images value as a whole, not field by field: a field left out is unset. |
body.settings.images.styleDescription |
body | string |
no | Free-text description of the project's visual identity, up to 400 characters (for example a palette or a mood). It is given to the model that writes each image prompt and appended to the prompt as Style: …. Absent or empty: none. |
body.settings.images.neverDepict |
body | string[] |
no | Subjects no generated image may show: up to 20 entries of 1 to 80 characters, at most 600 characters together once joined by , . They are appended to every image prompt as Never depict: …. Absent: the default list (official documents, seals and emblems, flags, identifiable real people). An empty array: nothing is excluded. |
body.settings.images.hero |
body | object |
no | Settings for the project's cover (hero) images: style, aspect and a standing prompt. Absent: covers use the article's imageStyle, the 16:9 aspect and no standing prompt. |
body.settings.images.hero.style |
body | "photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" |
no | Style of this project's cover images, replacing the article's imageStyle for covers. Absent: the article's imageStyle applies. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
body.settings.images.hero.aspect |
body | "16:9" | "1200x630" |
no | Shape of cover images (default 16:9). 16:9 is a wide banner; 1200x630 is the size social networks show for a shared link. Default: "16:9". |
body.settings.images.hero.prompt |
body | string |
no | Standing direction for every cover image, up to 600 characters, given to the model that writes the cover prompt (for example a recurring motif). Absent or empty: none. |
body.settings.images.inline |
body | object |
no | Settings for the images placed in the article body. |
body.settings.images.inline.style |
body | "photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" |
no | Style of this project's inline images, replacing the article's imageStyle for them. Absent: the article's imageStyle applies. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
body.settings.images.inline.aspect |
body | "4:3" | "1:1" |
no | Shape of inline images (default 4:3): 4:3 landscape or 1:1 square. Default: "4:3". |
body.websiteUrl |
body | string (uri) | null |
no | Address of the website the project writes for, an absolute http or https URL of up to 2000 characters, stored as given. A new address must point at a public host: a private, local or unresolvable one answers 400 INVALID_REQUEST. Setting it, on create or to a new address on update, queues a fetch of the site's icon (see iconUrl). null (the default on create) clears it; omitted on update keeps the current value. |
body.industry |
body | string |
no | Free-text industry of the site, up to 200 characters. Empty when omitted on create; unchanged when omitted on update. |
body.audience |
body | string |
no | Free-text description of who the articles are written for, up to 500 characters. The app starts a new article's audience from it. Empty when omitted on create; unchanged when omitted on update. |
body.language |
body | string |
no | Default language of the project, a language tag such as en or pt-BR: where a new article starts. Defaults to en on create. Changing it on update adds the new default to languages when it is not there yet. |
body.languages |
body | string[] |
no | Every language the project publishes in, as language tags: 1 to 10 entries. The default language is always added if missing and listed first, and more than 10 languages once it is added answers 400. Defaults to only the default language on create. On update the list replaces the stored one; removing a language that articles of the project are written in answers 409 CONFLICT, with those languages in details.inUse. |
body.defaultTone |
body | "professional" | "conversational" | "authoritative" | "practical" | "persuasive" |
no | Tone a new article starts from; each article can change it. professional is the default on create. The values: professional, conversational, authoritative, practical and persuasive. |
body.defaultWordCount |
body | integer |
no | Target length in words a new article starts from, from 200 to 10000; each article can change it. Defaults to 1200 on create. |
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 |
|---|---|---|---|
project |
object |
yes | The project, as it is after the request. |
project.id |
string (uuid) |
yes | Id of the project, used in every /projects/{projectId} route. |
project.workspaceId |
string (uuid) |
yes | Id of the workspace that owns the project. |
project.name |
string |
yes | Display name of the project, 1 to 120 characters. |
project.slug |
string |
yes | URL-safe identifier, unique within the workspace. Generated from name when not sent at creation, and never changed afterwards. |
project.description |
string |
yes | Free-text description of the project, up to 2000 characters; empty when unset. |
project.settings |
Record<string, unknown> |
yes | The stored settings object, with the keys exactly as they were sent. The only key the server reads is images (image-generation settings); imageSettings is that key with its defaults filled in. |
project.websiteUrl |
string | null |
yes | Address of the website the project writes for; null when none was given. |
project.iconUrl |
string | null |
yes | Address of the site's icon, copied to the media host: found by the website analysis, or fetched when websiteUrl is set or changed and by POST .../icon/refresh. null until one is found. No request sets it directly. |
project.industry |
string |
yes | Free-text industry of the site, up to 200 characters; empty when unset. |
project.audience |
string |
yes | Free-text description of who the articles are written for, up to 500 characters; empty when unset. The app starts a new article's audience from it. |
project.language |
string |
yes | The project's default language, a language tag such as en or pt-BR: where a new article starts. Always one of languages. |
project.languages |
string[] |
yes | Every language the project publishes in, as language tags, with the default language first. Articles are written in one of these. |
project.defaultTone |
string |
yes | Tone a new article starts from, one of professional, conversational, authoritative, practical, persuasive. Each article can change it. |
project.defaultWordCount |
integer |
yes | Target length in words a new article starts from, from 200 to 10000. Each article can change it. |
project.status |
"active" | "archived" |
yes | active, or archived: read-only until POST /api/workspaces/{workspaceId}/projects/{projectId}/restore makes it active again. |
project.createdAt |
string (date-time) |
yes | When the project was created, as an ISO 8601 timestamp. |
project.updatedAt |
string (date-time) |
yes | When the project row last changed (an update, an archive or a restore), as an ISO 8601 timestamp. |
project.imageSettings |
object |
yes | The project's image-generation settings as generation uses them: settings.images with every default filled in. A stored value that no longer validates reads as the defaults. |
project.imageSettings.styleDescription |
string | null |
yes | The project's style description, appended to every image prompt; null when none is set. |
project.imageSettings.neverDepict |
string[] |
yes | The subjects no image may show, in force: the project's own list, or the default list (official documents, seals and emblems, flags, identifiable real people) when it has none. Empty when the project excluded nothing. |
project.imageSettings.hero |
object |
yes | Cover (hero) image settings, defaults filled in. |
project.imageSettings.hero.style |
"photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" | null |
yes | Style for cover images; null when unset, in which case the article's imageStyle applies. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
project.imageSettings.hero.aspect |
"16:9" | "1200x630" |
yes | Shape of cover images: 16:9 or 1200x630 (the social-card size). |
project.imageSettings.hero.prompt |
string | null |
yes | Standing direction for cover images; null when none is set. |
project.imageSettings.inline |
object |
yes | Inline image settings, defaults filled in. |
project.imageSettings.inline.style |
"photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" | null |
yes | Style for inline images; null when unset, in which case the article's imageStyle applies. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
project.imageSettings.inline.aspect |
"4:3" | "1:1" |
yes | Shape of inline images: 4:3 or 1:1. |
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.projects.create({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
body: {
name: "example",
},
});
console.log(result);
pd.projects.get(input, init?)
Read a project
GET /api/workspaces/{workspaceId}/projects/{projectId}
Needs projects.read on the project: 404 when it is not in the workspace, 403 when it has members and the caller is not one. Carries the stored settings and imageSettings, the same with its defaults filled in. Works on archived projects.
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 |
path | string (uuid) |
yes | Id of a project of workspaceId. A project of another workspace answers 404 RESOURCE_NOT_FOUND, as if it did not exist. When the project has members, a workspace member who is not one of them answers 403 FORBIDDEN, and a project role can only narrow the permissions the member's workspace roles grant. |
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 |
|---|---|---|---|
project |
object |
yes | The project, as it is after the request. |
project.id |
string (uuid) |
yes | Id of the project, used in every /projects/{projectId} route. |
project.workspaceId |
string (uuid) |
yes | Id of the workspace that owns the project. |
project.name |
string |
yes | Display name of the project, 1 to 120 characters. |
project.slug |
string |
yes | URL-safe identifier, unique within the workspace. Generated from name when not sent at creation, and never changed afterwards. |
project.description |
string |
yes | Free-text description of the project, up to 2000 characters; empty when unset. |
project.settings |
Record<string, unknown> |
yes | The stored settings object, with the keys exactly as they were sent. The only key the server reads is images (image-generation settings); imageSettings is that key with its defaults filled in. |
project.websiteUrl |
string | null |
yes | Address of the website the project writes for; null when none was given. |
project.iconUrl |
string | null |
yes | Address of the site's icon, copied to the media host: found by the website analysis, or fetched when websiteUrl is set or changed and by POST .../icon/refresh. null until one is found. No request sets it directly. |
project.industry |
string |
yes | Free-text industry of the site, up to 200 characters; empty when unset. |
project.audience |
string |
yes | Free-text description of who the articles are written for, up to 500 characters; empty when unset. The app starts a new article's audience from it. |
project.language |
string |
yes | The project's default language, a language tag such as en or pt-BR: where a new article starts. Always one of languages. |
project.languages |
string[] |
yes | Every language the project publishes in, as language tags, with the default language first. Articles are written in one of these. |
project.defaultTone |
string |
yes | Tone a new article starts from, one of professional, conversational, authoritative, practical, persuasive. Each article can change it. |
project.defaultWordCount |
integer |
yes | Target length in words a new article starts from, from 200 to 10000. Each article can change it. |
project.status |
"active" | "archived" |
yes | active, or archived: read-only until POST /api/workspaces/{workspaceId}/projects/{projectId}/restore makes it active again. |
project.createdAt |
string (date-time) |
yes | When the project was created, as an ISO 8601 timestamp. |
project.updatedAt |
string (date-time) |
yes | When the project row last changed (an update, an archive or a restore), as an ISO 8601 timestamp. |
project.imageSettings |
object |
yes | The project's image-generation settings as generation uses them: settings.images with every default filled in. A stored value that no longer validates reads as the defaults. |
project.imageSettings.styleDescription |
string | null |
yes | The project's style description, appended to every image prompt; null when none is set. |
project.imageSettings.neverDepict |
string[] |
yes | The subjects no image may show, in force: the project's own list, or the default list (official documents, seals and emblems, flags, identifiable real people) when it has none. Empty when the project excluded nothing. |
project.imageSettings.hero |
object |
yes | Cover (hero) image settings, defaults filled in. |
project.imageSettings.hero.style |
"photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" | null |
yes | Style for cover images; null when unset, in which case the article's imageStyle applies. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
project.imageSettings.hero.aspect |
"16:9" | "1200x630" |
yes | Shape of cover images: 16:9 or 1200x630 (the social-card size). |
project.imageSettings.hero.prompt |
string | null |
yes | Standing direction for cover images; null when none is set. |
project.imageSettings.inline |
object |
yes | Inline image settings, defaults filled in. |
project.imageSettings.inline.style |
"photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" | null |
yes | Style for inline images; null when unset, in which case the article's imageStyle applies. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
project.imageSettings.inline.aspect |
"4:3" | "1:1" |
yes | Shape of inline images: 4:3 or 1:1. |
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.projects.get({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
projectId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);
pd.projects.update(input, init?)
Update a project
PATCH /api/workspaces/{workspaceId}/projects/{projectId}
Needs projects.update on the project. Only the fields sent change; slug cannot be changed. settings sets the keys it carries and keeps the others. settings.images configures image generation (style description, never-depict list, hero and inline aspect and style); the response's imageSettings is that with the defaults filled in. Removing a language that articles are written in answers 409 CONFLICT with those languages in details.inUse, unless deleteArticlesInRemovedLanguages is true. Allowed on an archived project too. Records a projects.updated audit entry listing the fields sent. Setting websiteUrl to a new address queues a fetch of the site's icon.
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 |
path | string (uuid) |
yes | Id of a project of workspaceId. A project of another workspace answers 404 RESOURCE_NOT_FOUND, as if it did not exist. When the project has members, a workspace member who is not one of them answers 403 FORBIDDEN, and a project role can only narrow the permissions the member's workspace roles grant. |
body |
body | object |
no | |
body.name |
body | string |
no | Display name of the project, 1 to 120 characters. Required to create one. |
body.description |
body | string |
no | Free-text description of the project, up to 2000 characters. Empty when omitted on create; unchanged when omitted on update. |
body.settings |
body | object |
no | Free-form settings object; any keys are stored as sent. Only images (image-generation settings) is read by the server, and it is validated. On create, omitted means {}. On update the keys sent replace the stored keys of the same name (images is replaced as a whole, not merged field by field) and keys not sent are kept. |
body.settings.images |
body | object |
no | The project's image settings. On update this replaces the stored images value as a whole, not field by field: a field left out is unset. |
body.settings.images.styleDescription |
body | string |
no | Free-text description of the project's visual identity, up to 400 characters (for example a palette or a mood). It is given to the model that writes each image prompt and appended to the prompt as Style: …. Absent or empty: none. |
body.settings.images.neverDepict |
body | string[] |
no | Subjects no generated image may show: up to 20 entries of 1 to 80 characters, at most 600 characters together once joined by , . They are appended to every image prompt as Never depict: …. Absent: the default list (official documents, seals and emblems, flags, identifiable real people). An empty array: nothing is excluded. |
body.settings.images.hero |
body | object |
no | Settings for the project's cover (hero) images: style, aspect and a standing prompt. Absent: covers use the article's imageStyle, the 16:9 aspect and no standing prompt. |
body.settings.images.hero.style |
body | "photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" |
no | Style of this project's cover images, replacing the article's imageStyle for covers. Absent: the article's imageStyle applies. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
body.settings.images.hero.aspect |
body | "16:9" | "1200x630" |
no | Shape of cover images (default 16:9). 16:9 is a wide banner; 1200x630 is the size social networks show for a shared link. Default: "16:9". |
body.settings.images.hero.prompt |
body | string |
no | Standing direction for every cover image, up to 600 characters, given to the model that writes the cover prompt (for example a recurring motif). Absent or empty: none. |
body.settings.images.inline |
body | object |
no | Settings for the images placed in the article body. |
body.settings.images.inline.style |
body | "photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" |
no | Style of this project's inline images, replacing the article's imageStyle for them. Absent: the article's imageStyle applies. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
body.settings.images.inline.aspect |
body | "4:3" | "1:1" |
no | Shape of inline images (default 4:3): 4:3 landscape or 1:1 square. Default: "4:3". |
body.websiteUrl |
body | string (uri) | null |
no | Address of the website the project writes for, an absolute http or https URL of up to 2000 characters, stored as given. A new address must point at a public host: a private, local or unresolvable one answers 400 INVALID_REQUEST. Setting it, on create or to a new address on update, queues a fetch of the site's icon (see iconUrl). null (the default on create) clears it; omitted on update keeps the current value. |
body.industry |
body | string |
no | Free-text industry of the site, up to 200 characters. Empty when omitted on create; unchanged when omitted on update. |
body.audience |
body | string |
no | Free-text description of who the articles are written for, up to 500 characters. The app starts a new article's audience from it. Empty when omitted on create; unchanged when omitted on update. |
body.language |
body | string |
no | Default language of the project, a language tag such as en or pt-BR: where a new article starts. Defaults to en on create. Changing it on update adds the new default to languages when it is not there yet. |
body.languages |
body | string[] |
no | Every language the project publishes in, as language tags: 1 to 10 entries. The default language is always added if missing and listed first, and more than 10 languages once it is added answers 400. Defaults to only the default language on create. On update the list replaces the stored one; removing a language that articles of the project are written in answers 409 CONFLICT, with those languages in details.inUse. |
body.defaultTone |
body | "professional" | "conversational" | "authoritative" | "practical" | "persuasive" |
no | Tone a new article starts from; each article can change it. professional is the default on create. The values: professional, conversational, authoritative, practical and persuasive. |
body.defaultWordCount |
body | integer |
no | Target length in words a new article starts from, from 200 to 10000; each article can change it. Defaults to 1200 on create. |
body.deleteArticlesInRemovedLanguages |
body | boolean |
no | With languages (or a new default language) that drops languages the project has articles in: permanently delete those articles in the same transaction instead of answering 409. Needs articles.delete on the project as well as projects.update. Published articles send article.unpublished (reason: "deleted"); each deleted article writes an articles.deleted audit entry. Default false: the 409 stands. |
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 |
|---|---|---|---|
project |
object |
yes | The project, as it is after the request. |
project.id |
string (uuid) |
yes | Id of the project, used in every /projects/{projectId} route. |
project.workspaceId |
string (uuid) |
yes | Id of the workspace that owns the project. |
project.name |
string |
yes | Display name of the project, 1 to 120 characters. |
project.slug |
string |
yes | URL-safe identifier, unique within the workspace. Generated from name when not sent at creation, and never changed afterwards. |
project.description |
string |
yes | Free-text description of the project, up to 2000 characters; empty when unset. |
project.settings |
Record<string, unknown> |
yes | The stored settings object, with the keys exactly as they were sent. The only key the server reads is images (image-generation settings); imageSettings is that key with its defaults filled in. |
project.websiteUrl |
string | null |
yes | Address of the website the project writes for; null when none was given. |
project.iconUrl |
string | null |
yes | Address of the site's icon, copied to the media host: found by the website analysis, or fetched when websiteUrl is set or changed and by POST .../icon/refresh. null until one is found. No request sets it directly. |
project.industry |
string |
yes | Free-text industry of the site, up to 200 characters; empty when unset. |
project.audience |
string |
yes | Free-text description of who the articles are written for, up to 500 characters; empty when unset. The app starts a new article's audience from it. |
project.language |
string |
yes | The project's default language, a language tag such as en or pt-BR: where a new article starts. Always one of languages. |
project.languages |
string[] |
yes | Every language the project publishes in, as language tags, with the default language first. Articles are written in one of these. |
project.defaultTone |
string |
yes | Tone a new article starts from, one of professional, conversational, authoritative, practical, persuasive. Each article can change it. |
project.defaultWordCount |
integer |
yes | Target length in words a new article starts from, from 200 to 10000. Each article can change it. |
project.status |
"active" | "archived" |
yes | active, or archived: read-only until POST /api/workspaces/{workspaceId}/projects/{projectId}/restore makes it active again. |
project.createdAt |
string (date-time) |
yes | When the project was created, as an ISO 8601 timestamp. |
project.updatedAt |
string (date-time) |
yes | When the project row last changed (an update, an archive or a restore), as an ISO 8601 timestamp. |
project.imageSettings |
object |
yes | The project's image-generation settings as generation uses them: settings.images with every default filled in. A stored value that no longer validates reads as the defaults. |
project.imageSettings.styleDescription |
string | null |
yes | The project's style description, appended to every image prompt; null when none is set. |
project.imageSettings.neverDepict |
string[] |
yes | The subjects no image may show, in force: the project's own list, or the default list (official documents, seals and emblems, flags, identifiable real people) when it has none. Empty when the project excluded nothing. |
project.imageSettings.hero |
object |
yes | Cover (hero) image settings, defaults filled in. |
project.imageSettings.hero.style |
"photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" | null |
yes | Style for cover images; null when unset, in which case the article's imageStyle applies. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
project.imageSettings.hero.aspect |
"16:9" | "1200x630" |
yes | Shape of cover images: 16:9 or 1200x630 (the social-card size). |
project.imageSettings.hero.prompt |
string | null |
yes | Standing direction for cover images; null when none is set. |
project.imageSettings.inline |
object |
yes | Inline image settings, defaults filled in. |
project.imageSettings.inline.style |
"photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" | null |
yes | Style for inline images; null when unset, in which case the article's imageStyle applies. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
project.imageSettings.inline.aspect |
"4:3" | "1:1" |
yes | Shape of inline images: 4:3 or 1:1. |
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.projects.update({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
projectId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);
pd.projects.delete(input, init?)
Delete a project
DELETE /api/workspaces/{workspaceId}/projects/{projectId}
Needs projects.delete. Permanently deletes the project and the content that belongs to it, including its articles. It cannot be undone; archive the project to keep the content. Works on archived projects. Records a projects.deleted audit entry.
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 |
path | string (uuid) |
yes | Id of a project of workspaceId. A project of another workspace answers 404 RESOURCE_NOT_FOUND, as if it did not exist. When the project has members, a workspace member who is not one of them answers 403 FORBIDDEN, and a project role can only narrow the permissions the member's workspace roles grant. |
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: the project or the membership was deleted. |
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.projects.delete({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
projectId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);
pd.projects.archive(input, init?)
Archive a project
POST /api/workspaces/{workspaceId}/projects/{projectId}/archive
Needs projects.update. Makes the project read-only: every other write in it (articles, images, generation, members) answers 409 CONFLICT until it is restored, while reads and exports keep working. Updating and deleting the project itself stay allowed. 409 CONFLICT when it is already archived. Records a projects.archived audit entry.
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 |
path | string (uuid) |
yes | Id of a project of workspaceId. A project of another workspace answers 404 RESOURCE_NOT_FOUND, as if it did not exist. When the project has members, a workspace member who is not one of them answers 403 FORBIDDEN, and a project role can only narrow the permissions the member's workspace roles grant. |
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 |
|---|---|---|---|
project |
object |
yes | The project, as it is after the request. |
project.id |
string (uuid) |
yes | Id of the project, used in every /projects/{projectId} route. |
project.workspaceId |
string (uuid) |
yes | Id of the workspace that owns the project. |
project.name |
string |
yes | Display name of the project, 1 to 120 characters. |
project.slug |
string |
yes | URL-safe identifier, unique within the workspace. Generated from name when not sent at creation, and never changed afterwards. |
project.description |
string |
yes | Free-text description of the project, up to 2000 characters; empty when unset. |
project.settings |
Record<string, unknown> |
yes | The stored settings object, with the keys exactly as they were sent. The only key the server reads is images (image-generation settings); imageSettings is that key with its defaults filled in. |
project.websiteUrl |
string | null |
yes | Address of the website the project writes for; null when none was given. |
project.iconUrl |
string | null |
yes | Address of the site's icon, copied to the media host: found by the website analysis, or fetched when websiteUrl is set or changed and by POST .../icon/refresh. null until one is found. No request sets it directly. |
project.industry |
string |
yes | Free-text industry of the site, up to 200 characters; empty when unset. |
project.audience |
string |
yes | Free-text description of who the articles are written for, up to 500 characters; empty when unset. The app starts a new article's audience from it. |
project.language |
string |
yes | The project's default language, a language tag such as en or pt-BR: where a new article starts. Always one of languages. |
project.languages |
string[] |
yes | Every language the project publishes in, as language tags, with the default language first. Articles are written in one of these. |
project.defaultTone |
string |
yes | Tone a new article starts from, one of professional, conversational, authoritative, practical, persuasive. Each article can change it. |
project.defaultWordCount |
integer |
yes | Target length in words a new article starts from, from 200 to 10000. Each article can change it. |
project.status |
"active" | "archived" |
yes | active, or archived: read-only until POST /api/workspaces/{workspaceId}/projects/{projectId}/restore makes it active again. |
project.createdAt |
string (date-time) |
yes | When the project was created, as an ISO 8601 timestamp. |
project.updatedAt |
string (date-time) |
yes | When the project row last changed (an update, an archive or a restore), as an ISO 8601 timestamp. |
project.imageSettings |
object |
yes | The project's image-generation settings as generation uses them: settings.images with every default filled in. A stored value that no longer validates reads as the defaults. |
project.imageSettings.styleDescription |
string | null |
yes | The project's style description, appended to every image prompt; null when none is set. |
project.imageSettings.neverDepict |
string[] |
yes | The subjects no image may show, in force: the project's own list, or the default list (official documents, seals and emblems, flags, identifiable real people) when it has none. Empty when the project excluded nothing. |
project.imageSettings.hero |
object |
yes | Cover (hero) image settings, defaults filled in. |
project.imageSettings.hero.style |
"photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" | null |
yes | Style for cover images; null when unset, in which case the article's imageStyle applies. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
project.imageSettings.hero.aspect |
"16:9" | "1200x630" |
yes | Shape of cover images: 16:9 or 1200x630 (the social-card size). |
project.imageSettings.hero.prompt |
string | null |
yes | Standing direction for cover images; null when none is set. |
project.imageSettings.inline |
object |
yes | Inline image settings, defaults filled in. |
project.imageSettings.inline.style |
"photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" | null |
yes | Style for inline images; null when unset, in which case the article's imageStyle applies. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
project.imageSettings.inline.aspect |
"4:3" | "1:1" |
yes | Shape of inline images: 4:3 or 1:1. |
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.projects.archive({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
projectId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);
pd.projects.restore(input, init?)
Restore an archived project
POST /api/workspaces/{workspaceId}/projects/{projectId}/restore
Needs projects.update; one of the few writes an archived project accepts. Makes the project active again, with its content as it was. 409 CONFLICT when the project is not archived. Records a projects.restored audit entry.
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 |
path | string (uuid) |
yes | Id of a project of workspaceId. A project of another workspace answers 404 RESOURCE_NOT_FOUND, as if it did not exist. When the project has members, a workspace member who is not one of them answers 403 FORBIDDEN, and a project role can only narrow the permissions the member's workspace roles grant. |
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 |
|---|---|---|---|
project |
object |
yes | The project, as it is after the request. |
project.id |
string (uuid) |
yes | Id of the project, used in every /projects/{projectId} route. |
project.workspaceId |
string (uuid) |
yes | Id of the workspace that owns the project. |
project.name |
string |
yes | Display name of the project, 1 to 120 characters. |
project.slug |
string |
yes | URL-safe identifier, unique within the workspace. Generated from name when not sent at creation, and never changed afterwards. |
project.description |
string |
yes | Free-text description of the project, up to 2000 characters; empty when unset. |
project.settings |
Record<string, unknown> |
yes | The stored settings object, with the keys exactly as they were sent. The only key the server reads is images (image-generation settings); imageSettings is that key with its defaults filled in. |
project.websiteUrl |
string | null |
yes | Address of the website the project writes for; null when none was given. |
project.iconUrl |
string | null |
yes | Address of the site's icon, copied to the media host: found by the website analysis, or fetched when websiteUrl is set or changed and by POST .../icon/refresh. null until one is found. No request sets it directly. |
project.industry |
string |
yes | Free-text industry of the site, up to 200 characters; empty when unset. |
project.audience |
string |
yes | Free-text description of who the articles are written for, up to 500 characters; empty when unset. The app starts a new article's audience from it. |
project.language |
string |
yes | The project's default language, a language tag such as en or pt-BR: where a new article starts. Always one of languages. |
project.languages |
string[] |
yes | Every language the project publishes in, as language tags, with the default language first. Articles are written in one of these. |
project.defaultTone |
string |
yes | Tone a new article starts from, one of professional, conversational, authoritative, practical, persuasive. Each article can change it. |
project.defaultWordCount |
integer |
yes | Target length in words a new article starts from, from 200 to 10000. Each article can change it. |
project.status |
"active" | "archived" |
yes | active, or archived: read-only until POST /api/workspaces/{workspaceId}/projects/{projectId}/restore makes it active again. |
project.createdAt |
string (date-time) |
yes | When the project was created, as an ISO 8601 timestamp. |
project.updatedAt |
string (date-time) |
yes | When the project row last changed (an update, an archive or a restore), as an ISO 8601 timestamp. |
project.imageSettings |
object |
yes | The project's image-generation settings as generation uses them: settings.images with every default filled in. A stored value that no longer validates reads as the defaults. |
project.imageSettings.styleDescription |
string | null |
yes | The project's style description, appended to every image prompt; null when none is set. |
project.imageSettings.neverDepict |
string[] |
yes | The subjects no image may show, in force: the project's own list, or the default list (official documents, seals and emblems, flags, identifiable real people) when it has none. Empty when the project excluded nothing. |
project.imageSettings.hero |
object |
yes | Cover (hero) image settings, defaults filled in. |
project.imageSettings.hero.style |
"photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" | null |
yes | Style for cover images; null when unset, in which case the article's imageStyle applies. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
project.imageSettings.hero.aspect |
"16:9" | "1200x630" |
yes | Shape of cover images: 16:9 or 1200x630 (the social-card size). |
project.imageSettings.hero.prompt |
string | null |
yes | Standing direction for cover images; null when none is set. |
project.imageSettings.inline |
object |
yes | Inline image settings, defaults filled in. |
project.imageSettings.inline.style |
"photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" | null |
yes | Style for inline images; null when unset, in which case the article's imageStyle applies. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
project.imageSettings.inline.aspect |
"4:3" | "1:1" |
yes | Shape of inline images: 4:3 or 1:1. |
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.projects.restore({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
projectId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);
pd.projects.refreshIcon(input, init?)
Refetch a project's website icon
POST /api/workspaces/{workspaceId}/projects/{projectId}/icon/refresh
Needs projects.update on the project. Queues a fetch of the icon of the project's websiteUrl and answers 202 at once. When the fetch finds a readable icon (PNG, ICO, JPEG, GIF or WebP; SVG is never used), the project's iconUrl changes to a new address; when it finds none, the current icon stays. 409 CONFLICT when the project has no websiteUrl. A request made while a fetch for the project is waiting or running joins it rather than queueing a second. Allowed on an archived project, as updating it is. Records a projects.icon_refreshed audit entry.
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 |
path | string (uuid) |
yes | Id of a project of workspaceId. A project of another workspace answers 404 RESOURCE_NOT_FOUND, as if it did not exist. When the project has members, a workspace member who is not one of them answers 403 FORBIDDEN, and a project role can only narrow the permissions the member's workspace roles grant. |
init |
init | { signal?: AbortSignal; timeoutMs?: number } |
no | The second argument: signal aborts the call, timeoutMs overrides the client's per-attempt timeout. |
Returns 202 Accepted
| Field | Type | Required | Description |
|---|---|---|---|
queued |
true |
yes | Always true: the fetch is queued. When it finds an icon, the project's iconUrl changes to a new address; when it finds none, the current icon stays. |
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.projects.refreshIcon({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
projectId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);
pd.projects.listMembers(input, init?)
List a project's members
GET /api/workspaces/{workspaceId}/projects/{projectId}/members
Needs projects.read on the project. A project with no members is open to every workspace member; once it has any, only its members (and holders of projects.members.manage, for administration only) can open 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 |
path | string (uuid) |
yes | Id of a project of workspaceId. A project of another workspace answers 404 RESOURCE_NOT_FOUND, as if it did not exist. When the project has members, a workspace member who is not one of them answers 403 FORBIDDEN, and a project role can only narrow the permissions the member's workspace roles grant. |
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 |
|---|---|---|---|
members |
object[] |
yes | The project's members. Empty means the project is open to every workspace member. |
members[].id |
string (uuid) |
yes | Id of this project membership (projectMemberId), used to change or remove it. Not the workspace membership id. |
members[].workspaceMemberId |
string (uuid) |
yes | Id of the member's workspace membership: memberId in GET .../members. |
members[].userId |
string |
yes | Id of the member's user account. |
members[].name |
string |
yes | The member's display name. |
members[].email |
string |
yes | The member's email address. |
members[].roleId |
string (uuid) | null |
yes | Id of the workspace role the member holds in this project, which narrows what they can do here to the permissions both that role and their workspace roles grant. null means no narrowing: their workspace roles apply unchanged. |
members[].roleName |
string | null |
yes | Name of the role roleId points to; null when roleId is null. |
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.projects.listMembers({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
projectId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);
pd.projects.addMember(input, init?)
Add a member to a project
POST /api/workspaces/{workspaceId}/projects/{projectId}/members
Needs projects.members.manage, which does not require being on the project. Adding the first member makes an open project restricted: from then on only its members can open it, so add yourself if you still need access. The member must belong to the workspace and roleId, when given, to the same workspace (400 INVALID_REQUEST); a member already on the project answers 409 CONFLICT, as does an archived project. Records a projects.members_changed audit entry and 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. |
projectId |
path | string (uuid) |
yes | Id of a project of workspaceId. A project of another workspace answers 404 RESOURCE_NOT_FOUND, as if it did not exist. When the project has members, a workspace member who is not one of them answers 403 FORBIDDEN, and a project role can only narrow the permissions the member's workspace roles grant. |
body |
body | object |
yes | |
body.workspaceMemberId |
body | string (uuid) |
yes | Id of the workspace membership to add (memberId in GET /api/workspaces/{workspaceId}/members). It must belong to the project's workspace, else 400 INVALID_REQUEST; already being on the project answers 409 CONFLICT. |
body.roleId |
body | string (uuid) | null |
no | Id of a role of the workspace (GET /api/workspaces/{workspaceId}/roles) that narrows what the member can do in this project to the permissions both it and their workspace roles grant. Omitted or null: no narrowing. A role of another workspace answers 400 INVALID_REQUEST. |
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 |
|---|---|---|---|
projectMemberId |
string (uuid) |
yes | Id of the new project membership, as id in GET .../members. |
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.projects.addMember({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
projectId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
body: {
workspaceMemberId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
},
});
console.log(result);
pd.projects.setMemberRole(input, init?)
Change a project member's role
PATCH /api/workspaces/{workspaceId}/projects/{projectId}/members/{projectMemberId}
Needs projects.members.manage. Replaces the member's project role in one update; null falls back to their workspace roles. 404 RESOURCE_NOT_FOUND when the member is not on the project, 409 CONFLICT when the project is archived. Records a projects.members_changed audit entry with the previous and new role.
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 |
path | string (uuid) |
yes | Id of a project of workspaceId. A project of another workspace answers 404 RESOURCE_NOT_FOUND, as if it did not exist. When the project has members, a workspace member who is not one of them answers 403 FORBIDDEN, and a project role can only narrow the permissions the member's workspace roles grant. |
projectMemberId |
path | string (uuid) |
yes | Id of a membership of this project, as id in GET .../members (not the workspace membership id). A membership of another project answers 404 RESOURCE_NOT_FOUND. |
body |
body | object |
yes | |
body.roleId |
body | string (uuid) | null |
yes | Id of the workspace role that becomes the member's project role, replacing the current one, or null to remove it so their workspace roles apply unchanged. Required: sending nothing is a 400, not a no-op. A role of another workspace answers 400 INVALID_REQUEST. |
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 |
|---|---|---|---|
member |
object |
yes | The membership after the change. |
member.id |
string (uuid) |
yes | Id of this project membership (projectMemberId), used to change or remove it. Not the workspace membership id. |
member.workspaceMemberId |
string (uuid) |
yes | Id of the member's workspace membership: memberId in GET .../members. |
member.userId |
string |
yes | Id of the member's user account. |
member.name |
string |
yes | The member's display name. |
member.email |
string |
yes | The member's email address. |
member.roleId |
string (uuid) | null |
yes | Id of the workspace role the member holds in this project, which narrows what they can do here to the permissions both that role and their workspace roles grant. null means no narrowing: their workspace roles apply unchanged. |
member.roleName |
string | null |
yes | Name of the role roleId points to; null when roleId is null. |
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.projects.setMemberRole({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
projectId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
projectMemberId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
body: {
roleId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
},
});
console.log(result);
pd.projects.removeMember(input, init?)
Remove a member from a project
DELETE /api/workspaces/{workspaceId}/projects/{projectId}/members/{projectMemberId}
Needs projects.members.manage. Removing the last member makes the project open to every workspace member again. 404 RESOURCE_NOT_FOUND when the membership is not on the project, 409 CONFLICT when the project is archived. Records a projects.members_changed audit entry.
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 |
path | string (uuid) |
yes | Id of a project of workspaceId. A project of another workspace answers 404 RESOURCE_NOT_FOUND, as if it did not exist. When the project has members, a workspace member who is not one of them answers 403 FORBIDDEN, and a project role can only narrow the permissions the member's workspace roles grant. |
projectMemberId |
path | string (uuid) |
yes | Id of a membership of this project, as id in GET .../members (not the workspace membership id). A membership of another project answers 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 |
|---|---|---|---|
ok |
true |
yes | Always true: the project or the membership was deleted. |
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.projects.removeMember({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
projectId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
projectMemberId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);
pd.projects.detectImageStyle(input, init?)
Detect the project's image style from its website
POST /api/workspaces/{workspaceId}/projects/{projectId}/image-style/detect
Needs projects.update on the project. Starts a detect run and answers 202 with it: the service reads the homepage and up to 3 article pages, takes up to 8 of their images (cover images first), and has a vision model name the closest preset and describe the style. The website must be set: without websiteUrl the answer is 409 CONFLICT. A site with fewer than 2 readable images of at least 200 × 200 ends failed. A run already queued or running of the same kind for this project is answered instead of a new one. A workspace may start 10 runs in any 24 hours, detections and proposals together (the detection onboarding starts on its own is outside the cap); past that the answer is 429 RATE_LIMITED with Retry-After (seconds until the oldest run of the window is 24 hours old) and details { retryAfterSeconds, limit, used }. Runs cost no credits. Follow the run with GET .../image-style/runs/latest until it is succeeded or failed, then apply a suggestion with POST .../image-style/apply.
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 |
path | string (uuid) |
yes | Id of a project of workspaceId. A project of another workspace answers 404 RESOURCE_NOT_FOUND, as if it did not exist. When the project has members, a workspace member who is not one of them answers 403 FORBIDDEN, and a project role can only narrow the permissions the member's workspace roles grant. |
init |
init | { signal?: AbortSignal; timeoutMs?: number } |
no | The second argument: signal aborts the call, timeoutMs overrides the client's per-attempt timeout. |
Returns 202 Accepted
| Field | Type | Required | Description |
|---|---|---|---|
run |
object |
yes | The run: a new one, queued, or the one of the same kind still running for this project. |
run.id |
string (uuid) |
yes | Id of the run, the runId that applyImageStyle takes. |
run.workspaceId |
string (uuid) |
yes | Id of the workspace that owns the project. |
run.projectId |
string (uuid) |
yes | Id of the project the run is for. |
run.kind |
"detect" | "propose" |
yes | detect: read the style of the website's images. propose: three alternatives that suit the site. |
run.status |
"queued" | "running" | "succeeded" | "failed" |
yes | queued, then running, then succeeded (with result) or failed (with error). A run that has not moved for 10 minutes is marked failed when the runs are read. |
run.result |
object<variant 1> | object<variant 2> | null |
yes | Once succeeded: for detect, { suggestion, observations, sampledImages }; for propose, { suggestions } (three). null before then and when failed. |
run.result<variant 1>.suggestion |
object |
yes | The style read from the website's images. |
run.result<variant 1>.suggestion.name |
string |
yes | A short name for the style, 1 to 60 characters, for example Warm editorial. |
run.result<variant 1>.suggestion.preset |
"photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" |
yes | The preset closest to the style. Applying the suggestion sets it as the project's hero.style and inline.style. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
run.result<variant 1>.suggestion.styleDescription |
string |
yes | The style in words, 1 to 400 characters: medium, palette, lighting, composition and mood. Applying the suggestion sets it as the project's styleDescription. |
run.result<variant 1>.suggestion.neverDepict |
string[] |
no | Subjects images in this style should not show, within the limits of the project's neverDepict (up to 20 entries of 1 to 80 characters, 600 together). Absent: applying the suggestion keeps the project's current list. |
run.result<variant 1>.observations |
string |
yes | What the images have in common, in a few sentences, up to 1000 characters. |
run.result<variant 1>.sampledImages |
integer |
yes | How many of the website's images were read, from 2 to 8. |
run.result<variant 2>.suggestions |
object[] |
yes | Exactly three styles: the first refines the current or detected style, the other two are clearly different. |
run.result<variant 2>.suggestions[].name |
string |
yes | A short name for the style, 1 to 60 characters, for example Warm editorial. |
run.result<variant 2>.suggestions[].preset |
"photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" |
yes | The preset closest to the style. Applying the suggestion sets it as the project's hero.style and inline.style. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
run.result<variant 2>.suggestions[].styleDescription |
string |
yes | The style in words, 1 to 400 characters: medium, palette, lighting, composition and mood. Applying the suggestion sets it as the project's styleDescription. |
run.result<variant 2>.suggestions[].neverDepict |
string[] |
no | Subjects images in this style should not show, within the limits of the project's neverDepict (up to 20 entries of 1 to 80 characters, 600 together). Absent: applying the suggestion keeps the project's current list. |
run.error |
string | null |
yes | Why the run failed, a sentence meant for people; null unless failed. |
run.requestedBy |
string | null |
yes | Id of the user who started the run (for an API key, the user who created the key); null for the run onboarding starts on its own, and once that user's account is deleted. |
run.appliedAt |
string (date-time) | null |
yes | When a suggestion of this run was last applied to the project; null if never. |
run.createdAt |
string (date-time) |
yes | When the run was started, as an ISO 8601 timestamp. |
run.updatedAt |
string (date-time) |
yes | When the run last changed, as an ISO 8601 timestamp. |
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.projects.detectImageStyle({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
projectId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);
pd.projects.proposeImageStyles(input, init?)
Propose three image styles for the project
POST /api/workspaces/{workspaceId}/projects/{projectId}/image-style/proposals
Needs projects.update on the project. Starts a propose run and answers 202 with it: a text model proposes three styles from the project's industry, audience, language, default brand voice, current image settings and latest detection, when there is one. The first refines the current or detected style; the other two are clearly different. Works without a website. A run already queued or running of the same kind for this project is answered instead of a new one. A workspace may start 10 runs in any 24 hours, detections and proposals together (the detection onboarding starts on its own is outside the cap); past that the answer is 429 RATE_LIMITED with Retry-After (seconds until the oldest run of the window is 24 hours old) and details { retryAfterSeconds, limit, used }. Runs cost no credits. Follow the run with GET .../image-style/runs/latest until it is succeeded or failed, then apply a suggestion with POST .../image-style/apply.
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 |
path | string (uuid) |
yes | Id of a project of workspaceId. A project of another workspace answers 404 RESOURCE_NOT_FOUND, as if it did not exist. When the project has members, a workspace member who is not one of them answers 403 FORBIDDEN, and a project role can only narrow the permissions the member's workspace roles grant. |
init |
init | { signal?: AbortSignal; timeoutMs?: number } |
no | The second argument: signal aborts the call, timeoutMs overrides the client's per-attempt timeout. |
Returns 202 Accepted
| Field | Type | Required | Description |
|---|---|---|---|
run |
object |
yes | The run: a new one, queued, or the one of the same kind still running for this project. |
run.id |
string (uuid) |
yes | Id of the run, the runId that applyImageStyle takes. |
run.workspaceId |
string (uuid) |
yes | Id of the workspace that owns the project. |
run.projectId |
string (uuid) |
yes | Id of the project the run is for. |
run.kind |
"detect" | "propose" |
yes | detect: read the style of the website's images. propose: three alternatives that suit the site. |
run.status |
"queued" | "running" | "succeeded" | "failed" |
yes | queued, then running, then succeeded (with result) or failed (with error). A run that has not moved for 10 minutes is marked failed when the runs are read. |
run.result |
object<variant 1> | object<variant 2> | null |
yes | Once succeeded: for detect, { suggestion, observations, sampledImages }; for propose, { suggestions } (three). null before then and when failed. |
run.result<variant 1>.suggestion |
object |
yes | The style read from the website's images. |
run.result<variant 1>.suggestion.name |
string |
yes | A short name for the style, 1 to 60 characters, for example Warm editorial. |
run.result<variant 1>.suggestion.preset |
"photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" |
yes | The preset closest to the style. Applying the suggestion sets it as the project's hero.style and inline.style. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
run.result<variant 1>.suggestion.styleDescription |
string |
yes | The style in words, 1 to 400 characters: medium, palette, lighting, composition and mood. Applying the suggestion sets it as the project's styleDescription. |
run.result<variant 1>.suggestion.neverDepict |
string[] |
no | Subjects images in this style should not show, within the limits of the project's neverDepict (up to 20 entries of 1 to 80 characters, 600 together). Absent: applying the suggestion keeps the project's current list. |
run.result<variant 1>.observations |
string |
yes | What the images have in common, in a few sentences, up to 1000 characters. |
run.result<variant 1>.sampledImages |
integer |
yes | How many of the website's images were read, from 2 to 8. |
run.result<variant 2>.suggestions |
object[] |
yes | Exactly three styles: the first refines the current or detected style, the other two are clearly different. |
run.result<variant 2>.suggestions[].name |
string |
yes | A short name for the style, 1 to 60 characters, for example Warm editorial. |
run.result<variant 2>.suggestions[].preset |
"photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" |
yes | The preset closest to the style. Applying the suggestion sets it as the project's hero.style and inline.style. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
run.result<variant 2>.suggestions[].styleDescription |
string |
yes | The style in words, 1 to 400 characters: medium, palette, lighting, composition and mood. Applying the suggestion sets it as the project's styleDescription. |
run.result<variant 2>.suggestions[].neverDepict |
string[] |
no | Subjects images in this style should not show, within the limits of the project's neverDepict (up to 20 entries of 1 to 80 characters, 600 together). Absent: applying the suggestion keeps the project's current list. |
run.error |
string | null |
yes | Why the run failed, a sentence meant for people; null unless failed. |
run.requestedBy |
string | null |
yes | Id of the user who started the run (for an API key, the user who created the key); null for the run onboarding starts on its own, and once that user's account is deleted. |
run.appliedAt |
string (date-time) | null |
yes | When a suggestion of this run was last applied to the project; null if never. |
run.createdAt |
string (date-time) |
yes | When the run was started, as an ISO 8601 timestamp. |
run.updatedAt |
string (date-time) |
yes | When the run last changed, as an ISO 8601 timestamp. |
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.projects.proposeImageStyles({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
projectId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);
pd.projects.latestImageStyleRuns(input, init?)
Read the project's latest image style runs
GET /api/workspaces/{workspaceId}/projects/{projectId}/image-style/runs/latest
Needs projects.update on the project. Answers the most recent detect run and the most recent propose run, each null when there is none. A run that has not moved for 10 minutes is marked failed when it is read, with error "The run stopped before it finished", so a lost run never stays queued or running.
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 |
path | string (uuid) |
yes | Id of a project of workspaceId. A project of another workspace answers 404 RESOURCE_NOT_FOUND, as if it did not exist. When the project has members, a workspace member who is not one of them answers 403 FORBIDDEN, and a project role can only narrow the permissions the member's workspace roles grant. |
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 |
|---|---|---|---|
detect |
object | null |
yes | The project's most recent detect run; null when it has none. |
detect.id |
string (uuid) |
yes | Id of the run, the runId that applyImageStyle takes. |
detect.workspaceId |
string (uuid) |
yes | Id of the workspace that owns the project. |
detect.projectId |
string (uuid) |
yes | Id of the project the run is for. |
detect.kind |
"detect" | "propose" |
yes | detect: read the style of the website's images. propose: three alternatives that suit the site. |
detect.status |
"queued" | "running" | "succeeded" | "failed" |
yes | queued, then running, then succeeded (with result) or failed (with error). A run that has not moved for 10 minutes is marked failed when the runs are read. |
detect.result |
object<variant 1> | object<variant 2> | null |
yes | Once succeeded: for detect, { suggestion, observations, sampledImages }; for propose, { suggestions } (three). null before then and when failed. |
detect.result<variant 1>.suggestion |
object |
yes | The style read from the website's images. |
detect.result<variant 1>.suggestion.name |
string |
yes | A short name for the style, 1 to 60 characters, for example Warm editorial. |
detect.result<variant 1>.suggestion.preset |
"photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" |
yes | The preset closest to the style. Applying the suggestion sets it as the project's hero.style and inline.style. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
detect.result<variant 1>.suggestion.styleDescription |
string |
yes | The style in words, 1 to 400 characters: medium, palette, lighting, composition and mood. Applying the suggestion sets it as the project's styleDescription. |
detect.result<variant 1>.suggestion.neverDepict |
string[] |
no | Subjects images in this style should not show, within the limits of the project's neverDepict (up to 20 entries of 1 to 80 characters, 600 together). Absent: applying the suggestion keeps the project's current list. |
detect.result<variant 1>.observations |
string |
yes | What the images have in common, in a few sentences, up to 1000 characters. |
detect.result<variant 1>.sampledImages |
integer |
yes | How many of the website's images were read, from 2 to 8. |
detect.result<variant 2>.suggestions |
object[] |
yes | Exactly three styles: the first refines the current or detected style, the other two are clearly different. |
detect.result<variant 2>.suggestions[].name |
string |
yes | A short name for the style, 1 to 60 characters, for example Warm editorial. |
detect.result<variant 2>.suggestions[].preset |
"photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" |
yes | The preset closest to the style. Applying the suggestion sets it as the project's hero.style and inline.style. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
detect.result<variant 2>.suggestions[].styleDescription |
string |
yes | The style in words, 1 to 400 characters: medium, palette, lighting, composition and mood. Applying the suggestion sets it as the project's styleDescription. |
detect.result<variant 2>.suggestions[].neverDepict |
string[] |
no | Subjects images in this style should not show, within the limits of the project's neverDepict (up to 20 entries of 1 to 80 characters, 600 together). Absent: applying the suggestion keeps the project's current list. |
detect.error |
string | null |
yes | Why the run failed, a sentence meant for people; null unless failed. |
detect.requestedBy |
string | null |
yes | Id of the user who started the run (for an API key, the user who created the key); null for the run onboarding starts on its own, and once that user's account is deleted. |
detect.appliedAt |
string (date-time) | null |
yes | When a suggestion of this run was last applied to the project; null if never. |
detect.createdAt |
string (date-time) |
yes | When the run was started, as an ISO 8601 timestamp. |
detect.updatedAt |
string (date-time) |
yes | When the run last changed, as an ISO 8601 timestamp. |
propose |
object | null |
yes | The project's most recent propose run; null when it has none. |
propose.id |
string (uuid) |
yes | Id of the run, the runId that applyImageStyle takes. |
propose.workspaceId |
string (uuid) |
yes | Id of the workspace that owns the project. |
propose.projectId |
string (uuid) |
yes | Id of the project the run is for. |
propose.kind |
"detect" | "propose" |
yes | detect: read the style of the website's images. propose: three alternatives that suit the site. |
propose.status |
"queued" | "running" | "succeeded" | "failed" |
yes | queued, then running, then succeeded (with result) or failed (with error). A run that has not moved for 10 minutes is marked failed when the runs are read. |
propose.result |
object<variant 1> | object<variant 2> | null |
yes | Once succeeded: for detect, { suggestion, observations, sampledImages }; for propose, { suggestions } (three). null before then and when failed. |
propose.result<variant 1>.suggestion |
object |
yes | The style read from the website's images. |
propose.result<variant 1>.suggestion.name |
string |
yes | A short name for the style, 1 to 60 characters, for example Warm editorial. |
propose.result<variant 1>.suggestion.preset |
"photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" |
yes | The preset closest to the style. Applying the suggestion sets it as the project's hero.style and inline.style. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
propose.result<variant 1>.suggestion.styleDescription |
string |
yes | The style in words, 1 to 400 characters: medium, palette, lighting, composition and mood. Applying the suggestion sets it as the project's styleDescription. |
propose.result<variant 1>.suggestion.neverDepict |
string[] |
no | Subjects images in this style should not show, within the limits of the project's neverDepict (up to 20 entries of 1 to 80 characters, 600 together). Absent: applying the suggestion keeps the project's current list. |
propose.result<variant 1>.observations |
string |
yes | What the images have in common, in a few sentences, up to 1000 characters. |
propose.result<variant 1>.sampledImages |
integer |
yes | How many of the website's images were read, from 2 to 8. |
propose.result<variant 2>.suggestions |
object[] |
yes | Exactly three styles: the first refines the current or detected style, the other two are clearly different. |
propose.result<variant 2>.suggestions[].name |
string |
yes | A short name for the style, 1 to 60 characters, for example Warm editorial. |
propose.result<variant 2>.suggestions[].preset |
"photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" |
yes | The preset closest to the style. Applying the suggestion sets it as the project's hero.style and inline.style. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
propose.result<variant 2>.suggestions[].styleDescription |
string |
yes | The style in words, 1 to 400 characters: medium, palette, lighting, composition and mood. Applying the suggestion sets it as the project's styleDescription. |
propose.result<variant 2>.suggestions[].neverDepict |
string[] |
no | Subjects images in this style should not show, within the limits of the project's neverDepict (up to 20 entries of 1 to 80 characters, 600 together). Absent: applying the suggestion keeps the project's current list. |
propose.error |
string | null |
yes | Why the run failed, a sentence meant for people; null unless failed. |
propose.requestedBy |
string | null |
yes | Id of the user who started the run (for an API key, the user who created the key); null for the run onboarding starts on its own, and once that user's account is deleted. |
propose.appliedAt |
string (date-time) | null |
yes | When a suggestion of this run was last applied to the project; null if never. |
propose.createdAt |
string (date-time) |
yes | When the run was started, as an ISO 8601 timestamp. |
propose.updatedAt |
string (date-time) |
yes | When the run last changed, as an ISO 8601 timestamp. |
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.projects.latestImageStyleRuns({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
projectId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);
pd.projects.applyImageStyle(input, init?)
Apply a detected or proposed image style
POST /api/workspaces/{workspaceId}/projects/{projectId}/image-style/apply
Needs projects.update on the project. Writes the chosen suggestion into settings.images: its preset becomes hero.style and inline.style, its styleDescription the style description, and its neverDepict, when it has one, the never-depict list. Aspects, the hero prompt and the other settings keys stay. The result is validated as PATCH validates settings.images, and the run's appliedAt is set. Images generated or regenerated afterwards follow it. Records a projects.image_style_applied audit entry and answers the project.
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 |
path | string (uuid) |
yes | Id of a project of workspaceId. A project of another workspace answers 404 RESOURCE_NOT_FOUND, as if it did not exist. When the project has members, a workspace member who is not one of them answers 403 FORBIDDEN, and a project role can only narrow the permissions the member's workspace roles grant. |
body |
body | object |
yes | |
body.runId |
body | string (uuid) |
yes | Id of a succeeded run of this project, from GET .../image-style/runs/latest. A run of another project answers 404; one that has not succeeded, 409. |
body.index |
body | integer |
no | Which suggestion to apply: 0 to 2 for a propose run, 0 (the default) for a detect run, which has one. Out of range for the run answers 400. Default: 0. |
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 |
|---|---|---|---|
project |
object |
yes | The project, as it is after the request. |
project.id |
string (uuid) |
yes | Id of the project, used in every /projects/{projectId} route. |
project.workspaceId |
string (uuid) |
yes | Id of the workspace that owns the project. |
project.name |
string |
yes | Display name of the project, 1 to 120 characters. |
project.slug |
string |
yes | URL-safe identifier, unique within the workspace. Generated from name when not sent at creation, and never changed afterwards. |
project.description |
string |
yes | Free-text description of the project, up to 2000 characters; empty when unset. |
project.settings |
Record<string, unknown> |
yes | The stored settings object, with the keys exactly as they were sent. The only key the server reads is images (image-generation settings); imageSettings is that key with its defaults filled in. |
project.websiteUrl |
string | null |
yes | Address of the website the project writes for; null when none was given. |
project.iconUrl |
string | null |
yes | Address of the site's icon, copied to the media host: found by the website analysis, or fetched when websiteUrl is set or changed and by POST .../icon/refresh. null until one is found. No request sets it directly. |
project.industry |
string |
yes | Free-text industry of the site, up to 200 characters; empty when unset. |
project.audience |
string |
yes | Free-text description of who the articles are written for, up to 500 characters; empty when unset. The app starts a new article's audience from it. |
project.language |
string |
yes | The project's default language, a language tag such as en or pt-BR: where a new article starts. Always one of languages. |
project.languages |
string[] |
yes | Every language the project publishes in, as language tags, with the default language first. Articles are written in one of these. |
project.defaultTone |
string |
yes | Tone a new article starts from, one of professional, conversational, authoritative, practical, persuasive. Each article can change it. |
project.defaultWordCount |
integer |
yes | Target length in words a new article starts from, from 200 to 10000. Each article can change it. |
project.status |
"active" | "archived" |
yes | active, or archived: read-only until POST /api/workspaces/{workspaceId}/projects/{projectId}/restore makes it active again. |
project.createdAt |
string (date-time) |
yes | When the project was created, as an ISO 8601 timestamp. |
project.updatedAt |
string (date-time) |
yes | When the project row last changed (an update, an archive or a restore), as an ISO 8601 timestamp. |
project.imageSettings |
object |
yes | The project's image-generation settings as generation uses them: settings.images with every default filled in. A stored value that no longer validates reads as the defaults. |
project.imageSettings.styleDescription |
string | null |
yes | The project's style description, appended to every image prompt; null when none is set. |
project.imageSettings.neverDepict |
string[] |
yes | The subjects no image may show, in force: the project's own list, or the default list (official documents, seals and emblems, flags, identifiable real people) when it has none. Empty when the project excluded nothing. |
project.imageSettings.hero |
object |
yes | Cover (hero) image settings, defaults filled in. |
project.imageSettings.hero.style |
"photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" | null |
yes | Style for cover images; null when unset, in which case the article's imageStyle applies. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
project.imageSettings.hero.aspect |
"16:9" | "1200x630" |
yes | Shape of cover images: 16:9 or 1200x630 (the social-card size). |
project.imageSettings.hero.prompt |
string | null |
yes | Standing direction for cover images; null when none is set. |
project.imageSettings.inline |
object |
yes | Inline image settings, defaults filled in. |
project.imageSettings.inline.style |
"photorealistic" | "editorial" | "minimalist-vector" | "3d-render" | "watercolor" | "corporate-tech" | "cinematic" | "illustration" | null |
yes | Style for inline images; null when unset, in which case the article's imageStyle applies. Values: photorealistic (natural-light documentary photograph, realistic textures, no stylisation), editorial (modern editorial illustration or photograph, clean composition, restrained palette), minimalist-vector (flat vector illustration, few shapes, solid colours, plenty of empty space), 3d-render (soft studio 3D render, smooth matte materials, simple forms), watercolor (loose watercolour painting, soft edges, muted washes), corporate-tech (clean technology visual in cool blues and greys, geometric shapes), cinematic (cinematic still, dramatic lighting, strong atmosphere, wide framing), illustration (hand-drawn illustration, confident linework, warm friendly palette). |
project.imageSettings.inline.aspect |
"4:3" | "1:1" |
yes | Shape of inline images: 4:3 or 1:1. |
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.projects.applyImageStyle({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
projectId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
body: {
runId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
},
});
console.log(result);