Deck Docs

Resource Reference

Learn which Public API endpoints are available, what they return, and how pagination works.

Resource Reference

This page documents the human-readable shape of the v1 Deck Public API. The machine-readable contract at /openapi is the complete source for endpoint methods, request bodies, filters, and response schemas.

Endpoint summary

MethodPathDescriptionPagination
GET/openapiOpenAPI 3.1 specificationnone
GET/meVerify the key and inspect resolved identitynone
GET/context, /org-members, /dashboard, /searchRead shared organization data or search product recordsvaries
GET/themesList themescursor
GET/themes/{themeId}Get a theme by IDnone
GET/insightsList insightscursor
GET/insights/{insightId}Get an insight by IDnone
GET, POST, PATCH, DELETE/themes, /insights, and their nested resourcesMaintain themes, insights, their links, and insight quotesvaries
GET, POST, PATCH, DELETE/categories, /segments, /contacts, /feedbackWork with feedback classification and customer datavaries
GET, POST/interviews, /surveys, /nps, /csv-uploads, /integrationsRead source data and start supported imports, syncs, or processingvaries
GET, POST/jobs and /jobs/{jobId}Create, list, and poll product async jobsvaries
GET/projectsList Projectscursor
POST/projectsCreate a Projectnone
GET/projects/{projectId}Get a Project by IDnone
PATCH/projects/{projectId}Update Project metadatanone
DELETE/projects/{projectId}Soft-delete a Project by archiving itnone
GET/initiativesList initiativescursor
GET/initiatives/{initiativeId}Get an initiative by IDnone
POST/build/projectsExecute one Project build mutationnone
POST/build/initiativesExecute one initiative build mutationnone
POST/build/opportunitiesExecute one opportunity build mutationnone
GET, POST, PATCH, DELETE/initiatives, /opportunities, and their nested resourcesRead and manage Build resources, evidence, sections, segments, and linksvaries
GET/support/cs/ticketsRead customer-service ticketsvaries
GET/subthemesList subthemesoffset
GET/subthemes/{subthemeId}Get a subtheme by IDnone
GET/competitorsList competitors and research statusnone
GET/competitors/overviewLandscape overviewnone
GET/competitors/{competitorId}Get one competitornone
GET/competitors/subthemes/{subthemeId}Competitor subtheme detailnone
GET/competitors/insightsCompetitor synthesis insightscursor
GET/competitors/insights/{insightId}One competitor synthesis insightnone
GET/competitors/opportunity-teasersOpportunity teasersnone
GET/competitors/opportunity-teasers/{teaserId}Teaser insightscursor
POST/competitors/researchStart or add-and-rerun researchnone
GET/competitors/research/{jobId}Poll a research jobnone
POST/competitors/promotePromote a finding or insight set to Opportunity Backlognone
POST/competitors/assign-insightsAppend competitor insights onto a backlog opportunitynone
GET/competitors/checkinsList check-in runscursor
GET/competitors/checkins/latestLatest check-in runnone
POST/competitors/checkinsEnable or disable check-ins (org admin)none

The table groups endpoint families so it remains readable as Deck evolves. Use /openapi when you need an exact route or schema; it is generated from the same shipped inventory used to verify Public API parity.

/me

Use this endpoint to confirm that your key works and see the identity Deck resolved from it.

Response fields

FieldMeaning
org_idThe authenticated organization
user_idThe key owner
roleThe key owner’s current role
scopeThe authorized scope for this endpoint (read for /me)

/themes

Lists themes for the authenticated organization.

Query parameters

ParameterTypeNotes
limitintegerdefault 50, max 100
cursorstringopaque pagination cursor

Theme fields

FieldMeaning
idTheme ID
nameTheme name
colorTheme color
notesOptional notes
insight_countNumber of linked insights
created_atCreation timestamp
updated_atLast update timestamp

/insights

Lists insights for the authenticated organization.

Query parameters

ParameterTypeNotes
limitintegerdefault 50, max 100
cursorstringopaque pagination cursor
theme_idstringfilter to a specific theme
sentimentstringPOSITIVE, NEGATIVE, NEUTRAL
categorystringcategory filter

Supported categories

  • PAIN_POINTS
  • DELIGHTS
  • GENERAL_FEEDBACK
  • FEATURE_REQUESTS
  • USABILITY_ISSUES
  • BUGS_AND_ERRORS

Insight list fields

FieldMeaning
idInsight ID
nameInsight title
sentimentSentiment classification
categoryInsight category
quoteRepresentative customer quote
themesLinked theme references
created_atCreation timestamp
updated_atLast update timestamp

/insights/{insightId}

Returns a single insight with richer source metadata.

Additional fields include:

  • feedback_id
  • contact_id
  • user_email
  • user_name
  • interview_date

/projects

Lists Projects for the authenticated organization.

POST /projects creates a Deck-side Project and seeds the canonical Overview, Evidence, and Success Metrics sections. Required body: title. Optional body fields: description, status, initiative_id, and owner_id.

Query parameters

ParameterTypeNotes
limitintegerdefault 50, max 100
cursorstringopaque pagination cursor
initiative_idstringfilter to Projects linked to an initiative
statusstringProject lifecycle status
external_providerstringlinear or jira

Supported statuses

  • not_started
  • in_progress
  • completed
  • archived

Project fields

FieldMeaning
idProject ID
titleProject title
slugURL slug
descriptionOptional short summary
statusProject lifecycle status
initiativeLinked initiative summary when present
external_linksJira or Linear link metadata when present
created_atCreation timestamp
updated_atLast update timestamp

/projects/{projectId}

Returns a single Project plus structured document sections and evidence references.

PATCH /projects/{projectId} updates Project metadata: title, description, status, initiative_id, owner_id, start_date, and target_date.

DELETE /projects/{projectId} soft-deletes the Project by archiving it. It does not delete or mutate Jira or Linear artifacts.

Additional fields:

  • sections
  • evidence_references
  • external_links
  • latest_evidence_story

Project sections include Overview, Evidence, and Success Metrics content when present.

/initiatives

Lists initiatives for the authenticated organization.

Query parameters

ParameterTypeNotes
limitintegerdefault 50, max 100
cursorstringopaque pagination cursor
statusstringinitiative lifecycle status

Supported statuses

  • draft
  • exploring
  • building
  • ready_to_act
  • completed
  • archived

Initiative fields

FieldMeaning
idInitiative ID
titleInitiative title
slugURL slug
descriptionOptional short summary
goalOptional goal statement
statusInitiative status
leveraged_insights_countNumber of linked insights
created_atCreation timestamp
updated_atLast update timestamp

/initiatives/{initiativeId}

Returns a single initiative plus structured content sections.

Additional fields:

  • sections
  • last_generated_at

Each section includes:

  • key
  • content
  • updated_at

Build write surfaces

Build writes are action-based and strictly bounded.

Required on every mutation:

  • Idempotency-Key header (1-128 chars)
  • one action payload per request
  • org policy that allows write scope for the key owner

Explicit non-goals:

  • backlog generation endpoints
  • standalone story generation endpoints outside approved Build actions
  • arbitrary delete endpoints
  • third-party Jira or Linear artifact creation

/build/projects

Executes one Project mutation action.

Supported actions

ActionRequired fieldsOptional fields
createtitlestatus, initiative_id, owner_id
update_titleproject_id, titlenone
update_statusproject_id, statusnone
archiveproject_idnone
set_initiativeproject_id, initiative_idinitiative_id may be null to make the Project standalone
upsert_sectionproject_id, section_key, contentnone
link_external_artifactproject_id, provider, external_url, display_title, one of external_id or external_keymetadata
unlink_external_artifactproject_id, providernone
assign_insightsproject_id, insight_idsreason
unassign_insightsproject_id, insight_idsnone
generate_evidence_storyproject_idnone

link_external_artifact stores Deck-side Jira or Linear metadata for artifacts that already exist. It does not create or modify provider artifacts.

/build/initiatives

Executes one initiative mutation action.

Supported actions

ActionRequired fieldsOptional fields
createtitlegoal, owner_id
update_titleinitiative_id, titlenone
update_goalinitiative_id, goalnone
update_statusinitiative_id, statusnone
upsert_sectioninitiative_id, section_type, contentmetadata
set_segmentsinitiative_id, segment_idsnone

/build/opportunities

Executes one opportunity mutation action.

Supported actions

ActionRequired fieldsOptional fields
archiveopportunity_idnone
set_segmentsopportunity_id, segment_idsnone
link_initiativeopportunity_id, initiative_idnone
create_initiative_from_opportunityopportunity_id, titlegoal, owner_id
assign_evidenceopportunity_id, and at least one ID across insight_ids, theme_ids, subtheme_idsthe other ID lists (max 100 each)

Idempotency behavior

  • Same key + same normalized payload returns the original response with idempotency.replayed=true
  • Same key + different payload returns 409 IDEMPOTENCY_CONFLICT
  • Reusing the same key while the original matching request is still running also returns 409 IDEMPOTENCY_CONFLICT

/subthemes

Lists subthemes synthesized from theme-level or segment-level analysis.

Subthemes are only available to organizations eligible for the subthemes feature.

Query parameters

ParameterTypeNotes
limitintegerdefault 50, max 100
offsetintegerzero-based offset
theme_idstringfilter to a specific theme
segment_idstringfilter to a specific segment when segments are enabled
qstringcase-insensitive search against pattern name or description

Subtheme fields

FieldMeaning
idSubtheme ID
nameSubtheme name
descriptionSubtheme description
insight_countNumber of contributing insights
sentiment_breakdownPositive, negative, and neutral counts
theme_idParent theme ID
theme_nameParent theme name
theme_colorParent theme color
segment_idSegment context when present
synthesized_atTimestamp of the synthesis used

/subthemes/{subthemeId}

Returns full synthesized subtheme detail.

Additional fields:

  • insight_ids
  • blocks
  • theme
  • related_subthemes

Use this endpoint when you need more than the summary list and want the full subtheme context.

/competitors

Reads and writes the in-app Competitors graph. The workspace must have Competitors enabled. Otherwise Deck returns 403 FEATURE_NOT_AVAILABLE.

This graph is separate from your first-party themes and insights. List responses include graph status (empty, importing, running, ready, or failed), optional last_job, competitor { id, name, domain } rows, and enabled_sources (g2, capterra, trustradius, reddit, app_store, play_store, linkedin). GET /competitors/overview returns the same enabled_sources. There is no source_type= query parameter.

Quote objects keep source and also include source_type, source_url, parent_text, and thread_role (standalone, post, comment, or reply). Reddit comments and LinkedIn replies include the parent post in parent_text.

The Public API does not enable or disable Competitors, and it does not delete a tracked competitor. Those actions live in Settings → Competitors.

Writes require write scope and an Idempotency-Key header (1–128 characters). Members can start research, add a competitor, promote a finding, and assign competitor insights onto a backlog item. Only organization admins can change the check-in schedule (POST /competitors/checkins returns 403 ROLE_NOT_ALLOWED for members).

POST /competitors/research

Merges the posted competitors with the set you already track and appends new reviews onto the published graph — the same behavior as adding a competitor in the app. An empty competitors array is 400. Research that is already running is 409 CONFLICT. A successful start returns 202 with { job_id, status }.

{
  "competitors": [{ "name": "Rival", "website": "rival.com" }],
  "reviews_per_source": 30
}

reviews_per_source is optional (10–100). The default is 30.

Your plan still caps how many competitors you can track. Adding a new company over that cap fails; researching companies you already track still works.

On the Free plan, your organization gets one competitor report. The API researches the first 2 competitors at 10 reviews per source. After the report is ready, this endpoint returns 402 PLAN_UPGRADE_REQUIRED. A run that fails does not use the report.

If the workspace does not have enough credits for the research, this endpoint returns 402 CREDIT_LIMIT_EXCEEDED before a job is created. During the competitor free window, research does not need credits.

Poll GET /competitors/research/{jobId} until the job is ready or failed. If the credits run out after the job starts, the job response is still HTTP 200 with error_code: CREDIT_LIMIT_EXCEEDED. The last published graph stays visible while research runs.

POST /competitors/promote

Promotes a competitor subtheme, opportunity teaser, or set of competitor synthesis insights into Opportunity Backlog.

{
  "source_type": "subtheme",
  "source_id": "…",
  "title": "Fix onboarding",
  "include_first_party_feedback": true
}

source_type is subtheme, opportunity_teaser, or insights. Rails use source_id and return the existing backlog item when you promote the same source again (existing: true). insights uses insight_ids (1–100 competitor synthesis insight IDs, not first-party Insights). Promoting the same sorted insight set again is also idempotent.

GET /competitors/insights

Lists competitor synthesis insights newest first. The response is { data, pagination }. Default limit is 50, max 100. Optional filters: competitor_id, subtheme_id, opportunity_id (teaser). These IDs are not first-party /insights rows.

GET /competitors/insights/{insightId}

Returns one competitor synthesis insight. Missing or other-org IDs are 404.

POST /competitors/assign-insights

Appends competitor synthesis insights onto any backlog opportunity. Duplicates are ignored. First-party matching is not re-run. Unknown, first-party, or other-org IDs fail the whole request (400).

{
  "opportunity_id": "…",
  "insight_ids": ["…"]
}

GET /competitors/checkins

Lists check-in runs newest first. The response is { data, pagination }. Pass the last run id as cursor. limit is 1–100 and defaults to 50.

Each run includes status, cadence, timestamps, and a snapshot. Empty runs store { "changed": false } only. When the snapshot has diffs, rank closer to 0 means the theme moved up; an impactScore increase of 1 means the opportunity is more valuable.

GET /competitors/checkins/latest

Returns the most recent check-in run, or null if none exist.

POST /competitors/checkins

Organization admins enable or disable periodic check-ins. This does not start a scrape immediately.

{
  "enabled": true,
  "cadence": "monthly"
}

cadence is weekly, monthly, or quarterly (7 / 30 / 90 elapsed days). If you enable check-ins without a cadence, Deck uses monthly. Check-ins require Competitors to be on.

Check-ins need a paid plan. On the Free plan, "enabled": true returns 402 PLAN_UPGRADE_REQUIRED. "enabled": false always works.

Use /openapi for the exact field types. Competitor synthesis insights and opportunity-teaser detail pages paginate with a cursor. Check-in lists paginate by run id.

Pagination

Cursor pagination

Used by:

  • themes
  • insights
  • projects
  • initiatives
  • competitor synthesis insights
  • competitor opportunity-teaser insights
  • competitor check-in runs

Response shape:

{
  "pagination": {
    "next_cursor": "opaque-string-or-null",
    "has_more": true
  }
}

Offset pagination

Used by:

  • subthemes

Response shape:

{
  "pagination": {
    "total": 120,
    "has_more": true,
    "offset": 0,
    "limit": 50
  }
}

OpenAPI spec

The latest API contract is available at:

/api/v1/openapi

Use it when you want the exact field types or need to generate a client.