> Portal Navigation:
> 
> - Append `.md` to any URL under `https://dev.wix.com/docs/` to get its markdown version.
> - Pages are either content pages (article or reference text) or menu pages (a list of links to child pages).
> - To get a menu page, truncate any URL to a parent path and append `.md` (e.g. `https://dev.wix.com/docs/sdk.md`, `https://dev.wix.com/docs/sdk/core-modules.md`).
> - Top-level index of all portals: https://dev.wix.com/docs/llms.txt
> - Full concatenated docs: https://dev.wix.com/docs/llms-full.txt

# ListBlogPostCandidates

# Package: seo

# Namespace: SeoBlogPostCandidateServiceV1

# Method link: https://dev.wix.com/docs/api-reference/business-management/seo/content-plan-blog-post-candidate-v1/list-blog-post-candidates.md

## Permission Scopes:
View SEO Settings: SCOPE.PROMOTE.VIEW-SEO

## Introduction

Retrieves a list of blog post candidates for a content plan flow.

Omit `contentPlanFlowId` to read the site's most recent successful flow.
A site whose flows are all still running, failed, or canceled returns a
not found error.

Omit `paging` to return every candidate in a single response. When
`paging` is present, `limit` accepts 1 to 100 and defaults to 50.

Results are sorted by the order the content plan assigns them, then by
descending keyword score. The sort isn't configurable.

---

## REST API

### Schema

```
 Method: listBlogPostCandidates
 Description: Retrieves a list of blog post candidates for a content plan flow.  Omit `contentPlanFlowId` to read the site's most recent successful flow. A site whose flows are all still running, failed, or canceled returns a not found error.  Omit `paging` to return every candidate in a single response. When `paging` is present, `limit` accepts 1 to 100 and defaults to 50.  Results are sorted by the order the content plan assigns them, then by descending keyword score. The sort isn't configurable.
 URL: https://www.wixapis.com/promote/seo/v1/content-plan-flows/{contentPlanFlowId}/blog-post-candidates
 Method: GET
 # Note: If the parameter `a.b` is listed under required parameters, `b` is only required if `a` is also present.
 Required parameters:  contentPlanFlowId
 Method parameters: 
   param name: contentPlanFlowId | type:   none | required: true 
   query param name: includeOnlyUnmarked | type: includeOnlyUnmarked | description: Whether to return only candidates that haven't been used for a blog post yet.  A candidate is marked as used when a blog post is created from it in the Wix Blog product. An app can read this flag but can't set it, so track the posts you've written on your own side as well.  Default: `false`, which returns every candidate.  
   param name: paging | type: CursorPaging    
        - name: limit | type: integer | description: Max items per page. Default 50, max 100.  | validation: minimum 0, maximum 100, format int32
        - name: cursor | type: string | description: Cursor from a previous response. Omit for the first page.  | validation: maxLength 16000
 Return type: ListBlogPostCandidatesResponse
  - name: blogPostCandidates | type: array<BlogPostCandidate> | description: Retrieved blog post candidates.  | validation: maxItems 1000
     - name: id | type: string | description: Blog post candidate GUID.  Treat this value as opaque. Don't parse it or build it yourself, and pass it back exactly as received. The individual GUIDs it's built from are available on `candidateData`.  | read-only: true | validation: maxLength 100
     - name: candidateData | type: CandidateData | description: IDs that identify the candidate and the flow that generated it.  
        - name: blogPostCandidateId | type: string | description: GUID of the blog post candidate within its content plan flow.  | read-only: true | validation: format GUID
        - name: contentPlanFlowId | type: string | description: GUID of the content plan flow that generated this candidate.  | read-only: true | validation: format GUID
     - name: briefData | type: BriefData | description: The blog post brief itself: the suggested title, the target keywords, and the search data behind them.  
        - name: h1Title | type: string | description: Suggested title for the blog post.  | validation: maxLength 1000
        - name: keyword | type: string | description: Keyword the blog post targets.  | validation: maxLength 1000
        - name: mainKeyword | type: string | description: Primary keyword for the page the blog post supports.  A page has a single main keyword, and several blog posts can support the same one.  | validation: maxLength 1000
        - name: serpData | type: SerpData | description: Search engine results data for `mainKeyword`, such as its search volume and how hard it is to rank for.  List Blog Post Candidates doesn't currently return this field.  
           - name: id | type: string | description: SerpDataResult GUID  | read-only: true | validation: format GUID
           - name: peopleAlsoAskSuggestions | type: array<PeopleAlsoAskQuestion> | description: list of people also ask questions  | validation: maxItems 4
              - name: question | type: string | description: people also ask question title  | validation: maxLength 10000
              - name: answers | type: array<PeopleAlsoAskAnswer> | description: answers to the question  | validation: maxItems 2
                 - name: title | type: string | description: people also ask answer title  | validation: maxLength 10000
                 - name: description | type: string | description: description of the answer  | validation: maxLength 10000
           - name: peopleAlsoSearchSuggestions | type: array<string> | description: list of related searches  | validation: maxItems 10, maxLength 10000
           - name: autocompleteSuggestions | type: array<string> | description: list of autocomplete suggestions  | validation: maxItems 15, maxLength 10000
        - name: pageUrl | type: string | description: URL of the site page the blog post is meant to support.  | validation: maxLength 1000
     - name: seoData | type: SeoSchema | description: SEO tags suggested for the blog post, such as its title tag and meta description.  
        - name: tags | type: array<Tag> | description: SEO tag information.  
           - name: type | type: string | description: SEO tag type.   Supported values: `title`, `meta`, `script`, `link`.  Which of these an API actually accepts depends on where the tag is being set: this list is not a blanket guarantee across every API that reuses this message. Site SEO Tags in particular accepts only `meta` (see `SiteSeoTags.tags`) and rejects `title`/`script`/`link` with a validation error even though they appear here — check the field description of the specific `tags`-typed field you're writing to for the types it actually supports and the error it returns.  Limitation: `title` and `script` (e.g. a `script` tag with `props.type` `"application/ld+json"` carrying structured data) are supported only when `custom` is unset or `false`. Setting `custom: true` on a `title` or `script` tag is rejected with `TAG_TYPE_NOT_ALLOWED`, because `custom: true` routes the write through the site's Advanced/Custom Tags list. To write structured data, omit `custom` (or set it to `false`).  
           - name: props | type: object | description: A `{"key": "value"}` pair object where each SEO tag property (`"name"`, `"content"`, `"rel"`, `"href"`) contains a value. For example: `{"name": "description", "content": "the description itself"}`.  
           - name: meta | type: object | description: SEO tag metadata. For example, `{"height": 300, "width": 240}`.  
           - name: children | type: string | description: SEO tag inner content. For example, `<title> inner content </title>`.  
           - name: custom | type: boolean | description: Whether the tag is a [custom tag](https://support.wix.com/en/article/adding-additional-meta-tags-to-your-sites-pages) — i.e. an entry from the site's Advanced/Custom Tags list.  Setting this to `true` on a write restricts which `type` values are accepted — the same restriction the Advanced/Custom Tags UI enforces. `title` and `script` tags (including JSON-LD structured data) must be sent with `custom` omitted or `false`; sending them with `custom: true` is rejected with `TAG_TYPE_NOT_ALLOWED`.  Note this is a separate restriction from Site SEO Tags' own type restriction on `SiteSeoTags.tags`: even with `custom` unset, Site SEO Tags rejects `script` (e.g. for site-wide structured data) unconditionally. There is currently no way to set site-wide, every-page structured data through any of these APIs — write a per-page `script` tag through the Item SEO Tags API instead.  This flag is scoped to that feature only. It is NOT an indicator of whether a standard tag (`title`, `description`, Open Graph, etc.) reflects a manually configured value versus a computed default/pattern — standard tags always resolve with `custom: false`, even when their content comes from a page's manually saved SEO title/description override. Don't use this field to verify whether a live page reflects a manual per-page SEO edit.  Limitation: when `ResolveStaticPageSeoTags` is called without `seoData`, the per-page SEO data is read only from the Vibe/Wix-managed-headless override store. That store holds nothing for classic Wix Editor or Wix Studio pages, so even genuine Advanced/Custom Tags saved on those pages are missing from the response entirely — there, `false` means this API could not tell, not that no custom tag exists. Pass `seoData` explicitly to resolve against a known set of tags.  
           - name: disabled | type: boolean | description: Whether the tag is disabled. If the tag is disabled, people can't find your page when searching for this phrase in search engines.  
        - name: settings | type: Settings | description: SEO general settings.  
           - name: preventAutoRedirect | type: boolean | description: Whether the [automatical redirect visits](https://support.wix.com/en/article/customizing-your-pages-seo-settings-in-the-seo-panel) from the old URL to the new one is enabled.   Default: `false` (automatical redirect is enabled).  
           - name: keywords | type: array<Keyword> | description: User-selected keyword terms for a specific page.  | validation: maxItems 5
              - name: term | type: string | description: Keyword value.  
              - name: isMain | type: boolean | description: Whether the keyword is the main focus keyword.  
              - name: origin | type: string | description: The source that added the keyword terms to the SEO settings.  | validation: maxLength 1000
  - name: pagingMetadata | type: CursorPagingMetadata | description: Paging metadata.  
     - name: count | type: integer | description: Items returned in this page.  | validation: format int32
     - name: cursors | type: Cursors | description: Cursors for next/previous page.  
        - name: next | type: string | description: Cursor for the next page.  | validation: maxLength 16000
        - name: prev | type: string | description: Cursor for the previous page.  | validation: maxLength 16000
     - name: hasNext | type: boolean | description: Whether there are more pages.  


```

### Examples

### List the unused blog post briefs for a content plan flow
Returns the briefs that haven't been turned into blog posts yet. Omit includeOnlyUnmarked to return every brief.

```curl
curl -X GET \
'https://www.wixapis.com/seo-content-plan-service/v1/content-plan-flows/d290f1ee-6c54-4b01-90e6-d701748f0851/blog-post-candidates?includeOnlyUnmarked=true' \
-H 'Authorization: <AUTH>'
```

---

## JavaScript SDK

### Schema

```
 Method: wixClientAdmin.seo.blogPostCandidates.listBlogPostCandidates(contentPlanFlowId, options)
 Description: Retrieves a list of blog post candidates for a content plan flow.  Omit `contentPlanFlowId` to read the site's most recent successful flow. A site whose flows are all still running, failed, or canceled returns a not found error.  Omit `paging` to return every candidate in a single response. When `paging` is present, `limit` accepts 1 to 100 and defaults to 50.  Results are sorted by the order the content plan assigns them, then by descending keyword score. The sort isn't configurable.
 # Note: If the parameter `a.b` is listed under required parameters, `b` is only required if `a` is also present.
 Required parameters:  contentPlanFlowId
 Method parameters: 
   param name: contentPlanFlowId | type: string | description: GUID of the content plan flow to retrieve candidates for.  Omit to read the site's most recent successful flow. | required: true | validation: format GUID
   param name: options | type: ListBlogPostCandidatesOptions  none  
        - name: includeOnlyUnmarked | type: boolean | description: Whether to return only candidates that haven't been used for a blog post yet.  A candidate is marked as used when a blog post is created from it in the Wix Blog product. An app can read this flag but can't set it, so track the posts you've written on your own side as well.  Default: `false`, which returns every candidate.  
        - name: paging | type: CursorPaging | description: Cursor paging. Omit for the first page.  Omit this object entirely to return every candidate in a single response.  
           - name: limit | type: integer | description: Max items per page. Default 50, max 100.  | validation: minimum 0, maximum 100, format int32
           - name: cursor | type: string | description: Cursor from a previous response. Omit for the first page.  | validation: maxLength 16000
 Return type: PROMISE<ListBlogPostCandidatesResponse>
  - name: blogPostCandidates | type: array<BlogPostCandidate> | description: Retrieved blog post candidates.  | validation: maxItems 1000
     - name: _id | type: string | description: Blog post candidate GUID.  Treat this value as opaque. Don't parse it or build it yourself, and pass it back exactly as received. The individual GUIDs it's built from are available on `candidateData`.  | read-only: true | validation: maxLength 100
     - name: candidateData | type: CandidateData | description: IDs that identify the candidate and the flow that generated it.  
        - name: blogPostCandidateId | type: string | description: GUID of the blog post candidate within its content plan flow.  | read-only: true | validation: format GUID
        - name: contentPlanFlowId | type: string | description: GUID of the content plan flow that generated this candidate.  | read-only: true | validation: format GUID
     - name: briefData | type: BriefData | description: The blog post brief itself: the suggested title, the target keywords, and the search data behind them.  
        - name: h1Title | type: string | description: Suggested title for the blog post.  | validation: maxLength 1000
        - name: keyword | type: string | description: Keyword the blog post targets.  | validation: maxLength 1000
        - name: mainKeyword | type: string | description: Primary keyword for the page the blog post supports.  A page has a single main keyword, and several blog posts can support the same one.  | validation: maxLength 1000
        - name: serpData | type: SerpData | description: Search engine results data for `mainKeyword`, such as its search volume and how hard it is to rank for.  List Blog Post Candidates doesn't currently return this field.  
           - name: _id | type: string | description: SerpDataResult GUID  | read-only: true | validation: format GUID
           - name: peopleAlsoAskSuggestions | type: array<PeopleAlsoAskQuestion> | description: list of people also ask questions  | validation: maxItems 4
              - name: question | type: string | description: people also ask question title  | validation: maxLength 10000
              - name: answers | type: array<PeopleAlsoAskAnswer> | description: answers to the question  | validation: maxItems 2
                 - name: title | type: string | description: people also ask answer title  | validation: maxLength 10000
                 - name: description | type: string | description: description of the answer  | validation: maxLength 10000
           - name: peopleAlsoSearchSuggestions | type: array<string> | description: list of related searches  | validation: maxItems 10, maxLength 10000
           - name: autocompleteSuggestions | type: array<string> | description: list of autocomplete suggestions  | validation: maxItems 15, maxLength 10000
        - name: pageUrl | type: string | description: URL of the site page the blog post is meant to support.  | validation: maxLength 1000
     - name: seoData | type: SeoSchema | description: SEO tags suggested for the blog post, such as its title tag and meta description.  
        - name: tags | type: array<Tag> | description: SEO tag information.  
           - name: type | type: string | description: SEO tag type.   Supported values: `title`, `meta`, `script`, `link`.  Which of these an API actually accepts depends on where the tag is being set: this list is not a blanket guarantee across every API that reuses this message. Site SEO Tags in particular accepts only `meta` (see `SiteSeoTags.tags`) and rejects `title`/`script`/`link` with a validation error even though they appear here — check the field description of the specific `tags`-typed field you're writing to for the types it actually supports and the error it returns.  Limitation: `title` and `script` (e.g. a `script` tag with `props.type` `"application/ld+json"` carrying structured data) are supported only when `custom` is unset or `false`. Setting `custom: true` on a `title` or `script` tag is rejected with `TAG_TYPE_NOT_ALLOWED`, because `custom: true` routes the write through the site's Advanced/Custom Tags list. To write structured data, omit `custom` (or set it to `false`).  
           - name: props | type: object | description: A `{"key": "value"}` pair object where each SEO tag property (`"name"`, `"content"`, `"rel"`, `"href"`) contains a value. For example: `{"name": "description", "content": "the description itself"}`.  
           - name: meta | type: object | description: SEO tag metadata. For example, `{"height": 300, "width": 240}`.  
           - name: children | type: string | description: SEO tag inner content. For example, `<title> inner content </title>`.  
           - name: custom | type: boolean | description: Whether the tag is a [custom tag](https://support.wix.com/en/article/adding-additional-meta-tags-to-your-sites-pages) — i.e. an entry from the site's Advanced/Custom Tags list.  Setting this to `true` on a write restricts which `type` values are accepted — the same restriction the Advanced/Custom Tags UI enforces. `title` and `script` tags (including JSON-LD structured data) must be sent with `custom` omitted or `false`; sending them with `custom: true` is rejected with `TAG_TYPE_NOT_ALLOWED`.  Note this is a separate restriction from Site SEO Tags' own type restriction on `SiteSeoTags.tags`: even with `custom` unset, Site SEO Tags rejects `script` (e.g. for site-wide structured data) unconditionally. There is currently no way to set site-wide, every-page structured data through any of these APIs — write a per-page `script` tag through the Item SEO Tags API instead.  This flag is scoped to that feature only. It is NOT an indicator of whether a standard tag (`title`, `description`, Open Graph, etc.) reflects a manually configured value versus a computed default/pattern — standard tags always resolve with `custom: false`, even when their content comes from a page's manually saved SEO title/description override. Don't use this field to verify whether a live page reflects a manual per-page SEO edit.  Limitation: when `ResolveStaticPageSeoTags` is called without `seoData`, the per-page SEO data is read only from the Vibe/Wix-managed-headless override store. That store holds nothing for classic Wix Editor or Wix Studio pages, so even genuine Advanced/Custom Tags saved on those pages are missing from the response entirely — there, `false` means this API could not tell, not that no custom tag exists. Pass `seoData` explicitly to resolve against a known set of tags.  
           - name: disabled | type: boolean | description: Whether the tag is disabled. If the tag is disabled, people can't find your page when searching for this phrase in search engines.  
        - name: settings | type: Settings | description: SEO general settings.  
           - name: preventAutoRedirect | type: boolean | description: Whether the [automatical redirect visits](https://support.wix.com/en/article/customizing-your-pages-seo-settings-in-the-seo-panel) from the old URL to the new one is enabled.   Default: `false` (automatical redirect is enabled).  
           - name: keywords | type: array<Keyword> | description: User-selected keyword terms for a specific page.  | validation: maxItems 5
              - name: term | type: string | description: Keyword value.  
              - name: isMain | type: boolean | description: Whether the keyword is the main focus keyword.  
              - name: origin | type: string | description: The source that added the keyword terms to the SEO settings.  | validation: maxLength 1000
  - name: pagingMetadata | type: CursorPagingMetadata | description: Paging metadata.  
     - name: count | type: integer | description: Items returned in this page.  | validation: format int32
     - name: cursors | type: Cursors | description: Cursors for next/previous page.  
        - name: next | type: string | description: Cursor for the next page.  | validation: maxLength 16000
        - name: prev | type: string | description: Cursor for the previous page.  | validation: maxLength 16000
     - name: hasNext | type: boolean | description: Whether there are more pages.  


```

### Examples

### listBlogPostCandidates
```javascript
import { blogPostCandidates } from '@wix/seo';

async function listBlogPostCandidates(contentPlanFlowId,options) {
  const response = await blogPostCandidates.listBlogPostCandidates(contentPlanFlowId,options);
};
```

### listBlogPostCandidates (with elevated permissions)
```javascript
import { blogPostCandidates } from '@wix/seo';
import { auth } from '@wix/essentials';

async function myListBlogPostCandidatesMethod(contentPlanFlowId,options) {
  const elevatedListBlogPostCandidates = auth.elevate(blogPostCandidates.listBlogPostCandidates);
  const response = await elevatedListBlogPostCandidates(contentPlanFlowId,options);
}
```

### listBlogPostCandidates (self-hosted)
Self-hosted SDK calls require you to [create a client](https://dev.wix.com/docs/sdk/articles/work-with-the-sdk/about-the-wix-client.md).

```javascript
import { createClient } from '@wix/sdk';
import { blogPostCandidates } from '@wix/seo';
// Import the auth strategy for the relevant access type
// Import the relevant host module if needed

const myWixClient = createClient ({
  modules: { blogPostCandidates },
  // Include the auth strategy and host as relevant
});


async function listBlogPostCandidates(contentPlanFlowId,options) {
  const response = await myWixClient.blogPostCandidates.listBlogPostCandidates(contentPlanFlowId,options);
};
```

---