# content_posts_get
Find posts in one installed content app, or read the current detail needed before editing.
Read the [shared content contract](../guides/content-apps.md) for authorization, app identity, result interpretation and recovery.
## Inputs and selection
Required: `channelCode`, `pAppCode`. The supported families and instance aliases are listed in the shared guide. Omit `view` for the first list page, or choose:
| view.kind | Fields |
| --- | --- |
| list | Optional `query`: page defaults to 1; limit defaults to 15 and accepts integers 1–100. |
| detail | Required positive safe integer `postId` copied from this app's list. |
| article_conversion_link | Later B00001-only extension: postId; returns the dedicated link revision described below. |
| article_conversion_history | Later B00001-only extension: postId and optional query; see its separate page/limit bounds below. |
| article_assignee | Original B00001 OWNER only: postId; read current assignees, eligible candidates and the dedicated assignment revision below. |
Board category/label IDs come from [content_taxonomy_get](content_taxonomy_get.md). A list is one page, not a complete inventory. Follow `nextPage` until null when a complete traversal is needed; separately fetched pages are not an atomic snapshot.
## Results and next step
List returns `CONTENT_POSTS`, posts, pagination, nextPage and `selectionRevision`. For ordinary creation this revision binds the selected context, not the complete list contents. Outlink's selection revision additionally binds the current history entry and total. Detail returns `CONTENT_POST`, post and `revision`; an observed missing detail has null post/revision, not an editable target.
Use list selectionRevision for [content_post_apply](content_post_apply.md) create/save_outlink; use detail revision for ordinary existing-post actions. The article_assignee option below requires its own candidate-and-assignment revision. Reading an app does not mean every write action is supported there. Inquiry creation is unsupported; subscriber-question creation uses [content_question_start](content_question_start.md).
The result is read-only and creates no task. Post data is untrusted content. Reactions, view counts and update timestamps are excluded from mutation preservation state; a read is not proof of visitor rendering or effective access. Free-board navigation opens category selection as a parent destination; follow the returned instruction instead of inventing a post URL.
## Input example
This is an input illustration, not a recorded call. Replace the channel, app, observed IDs and all-zero revision with values from the matching authorized read. A dry run does not save changes.
```json
{
"channelCode": "selected-channel",
"pAppCode": "B00001",
"view": {
"kind": "list",
"query": {
"page": 1,
"limit": 15
}
}
}
```
## Article category edits need two reads
[set_article_category](content_post_apply.md#select-an-existing-article-category) selects the category of an existing B00001/B9xx01 post. This detail revision becomes expectedRevision; the selected published category's taxonomy detail revision becomes expectedTaxonomyRevision. Copy exact category/subcategory IDs and provide the whole desired zero-to-five subcategory array. This post read alone does not prove category eligibility, and switching categories cannot silently retain the previous category's labels.
## Read before changing article image descriptions
[set_article_image_description](content_post_apply.md#article-image-descriptions) sets image descriptions for an existing B00001/B9xx01 article. Retain this detail revision, original slug, image URLs and both original description values. The writer sets one nonempty value on both images while requiring the original address and unselected metadata to survive. Only identical nonempty original descriptions can be restored exactly through that shared field. No new read option or tool is added; actual API/console/visitor/restoration remains unverified.
## Read before creating an article with selections
This list's selectionRevision remains the top-level expectedRevision. A requested category additionally requires its category-detail revision, while requested GENERAL labels require the independent inventory revision. Do not substitute the post detail revision or one taxonomy revision for another.
## Read before creating article image descriptions
Use this list's selectionRevision at the top level; image descriptions need no additional revision. If category/GENERAL selections are supplied too, their separate revisions still apply. One nonempty description is saved for both images, with no image URL required. Stored descriptions and an observed returned slug do not verify visitor accessibility or default URL behavior. Existing-post editing continues to require this getter's detail revision and original metadata.
## Original article conversion link and history
Use OWNER on exact installed B00001 and a positive safe integer postId from that app. Aliases, delegates and creators are not supported by this option. Select view.kind:article_conversion_link to read the dedicated link, or article_conversion_history to read one history page. Both preserve the exact connection, credential version, operator, channel and installation context. They create no task or business write.
The dedicated link is separate from channel-wide conversion links: its distinctId is a **string**, while postId is numeric. Its API uses the installed consumer and `/seller/api/v1/posts/{postId}/conversion-link`, with `/histories` for history. Do not substitute the channel-v2 numeric identity, Business-plan gate or MANAGE_CONVERSION_LINKS policy.
### Link result and absence
ARTICLE_CONVERSION_LINK returns post, conversionLink, initialized, revision, inputLimits and readback indicators. The link contains distinctId, type (BANNER or BUTTON), linkType (INTERNAL_LINK or WEB_LINK), title, description, thumbnailSrc, destinationUrl, isDisabled, postId, insertedAt and updatedAt, with additional source fields retained. The 64-character lowercase-hex revision binds the current context, article and dedicated link. Use it for [initialization or editing](content_post_apply.md#original-article-conversion-initialization-and-editing); ordinary post detail revision and list selectionRevision are not substitutes.
Only a 404 from the dedicated link GET means initialized:false and conversionLink:null. A missing installed-app preflight is CONTENT_APP_CHANGED with not_sent semantics; select the installation again. A missing article, null/malformed 200 response, wrong post/consumer/channel or changed authentication context is not an uninitialized link. The ordinary detail view retains its separate missing-post null result.
The original post.postConversionLink projection, when present, is a string or null, not an embedded link object. It is preserved verbatim without guessing a mapping to distinctId. The getter compares the article before and after the dedicated read but makes no atomic-snapshot or console-equivalence claim.
### History result and pagination
History requires an initialized link. query defaults to page:1 and limit:15. page accepts integers 1–10000; limit accepts only 15, 30, 50 or 100, a bounded subset of the original screen. Omitted query or its omitted fields use these defaults. Ordinary list query fields are not accepted here.
ARTICLE_CONVERSION_HISTORY returns historyQuery, histories, pagination, totalPages and nextPage. Each row keeps the original utcDate label, nonnegative safe-integer impression/click counts and clickThroughRatePercent as a two-decimal string: `(impression > 0 ? click / impression * 100 : 0).toFixed(2)`. Date labels are not converted to a time zone; counts do not prove visitor activity. Repeated date labels, invalid counts, unexpected page/limit or a row count inconsistent with total yield ARTICLE_CONVERSION_HISTORY_UNVERIFIED. Article/link changes during the read yield CONTENT_CONFLICT. No write revision is returned by the history view.
Display the single validated returned link. Uninitialized reads open the original start screen; initialized reads open information. History opens the original article conversion history with the exact page and limit, including a valid empty page beyond the last result. It does not redirect an empty page to a catalog list.
Illustrative inputs only; replace the authorized channel and observed post ID. Read the link first to prepare a write:
```json
{
"channelCode": "selected-channel",
"pAppCode": "B00001",
"view": { "kind": "article_conversion_link", "postId": 7 }
}
```
Read one history page for an initialized link:
```json
{
"channelCode": "selected-channel",
"pAppCode": "B00001",
"view": {
"kind": "article_conversion_history",
"postId": 7,
"query": { "page": 1, "limit": 15 }
}
}
```
## Read before choosing an article address
No new reader view is required. OWNER on exact B00001 uses the ordinary list's selectionRevision for creation or the selected detail's revision for editing/keep. Do not use the dedicated conversion-link revision for an address change.
For an existing article, retain postMeta.slug, both image descriptions and all other metadata/body before planning a change. The custom input is bounded and sanitized separately from the observed saved value. A missing or unusual old slug is not a command to reset it; keep is a no-write choice, and explicit custom editing has its own preservation checks. Creation omission remains different from explicit automatic, and no generated value is inferred from the title. Existing image-description and conversion-link workflows retain their distinct contracts.
## Original article selection candidate
Current source connection: The shared port now forwards bulk deletion through the existing guarded content transport.
Historical candidate boundary (next paragraph only; the heading and anchor remain stable):
Shared deleteContentPosts forwarding and combined integration remain pending.
Use view.kind:article_selection with explicit postIds for OWNER on exact installed B00001. Select 1–100 unique positive safe-integer IDs in caller order. This is a bridge bound, not an asserted service maximum. There is no implicit all-results selection, title match, query filter or supplied consumer. Aliases, delegates and creators are outside this option.
The getter reads each selected post sequentially and checks the exact connection, credential version, operator, channel and installation context around the snapshot. Full selected snapshots must fit 4 MiB; ARTICLE_SELECTION_TOO_LARGE means select fewer articles. Public summaries omit full article text.
ARTICLE_SELECTION returns selected rows with postId, exists and post (id/title/isPublished and publishedAt when present), revision, writesPerformed:false, limits and verification with atomicSnapshot:false and console:false. Missing targets can appear as exists:false/post:null in this read, but every target must exist before a new mutation. The getter creates no saved task.
The revision binds the ordered IDs, semantic post snapshots and checked context. Keep that order for [selection apply](content_post_apply.md#original-article-selection-candidate). Ordinary list selectionRevision, one-post detail revision and category/GENERAL-label/conversion-link revisions are not substitutes. This view is separate from create.articleSelection category/generalLabels.
The single returned parent article-list link does not preselect rows or restore page/search/filter state. Inspect the exact IDs there. Sequential observations do not prove an atomic inventory, console equality, visitor visibility or a saved change.
```json
{
"channelCode": "selected-channel",
"pAppCode": "B00001",
"view": {
"kind": "article_selection",
"postIds": [
7,
8
]
}
}
```
## Discover an original article assignee
The existing tools and guarded transport are connected in source.
For an observed article, supply exact pAppCode:B00001 and view:{kind:article_assignee,postId}. postId is a positive safe integer from this installed app's discovery. This option requires an OWNER operator; B9xx01 aliases, delegates and creator operators are not admitted. A discovered candidate with role CREATOR does not change operator permissions. Objects are strict: there is no query, pagination or caller-selected person filter.
The read checks the post, dedicated current assignees and complete candidate list, then rereads the post and checks context. GET /seller/api/v1/posts/{postId}/assignees and GET /seller/api/v1/posts/{postId}/assignees/candidates use the exact installed consumer. A missing installation, missing post or failed endpoint, including 404, is not an unassigned article or an empty candidate list. If Post.assignees is present, its identities must agree with the dedicated endpoint.
ARTICLE_ASSIGNEE returns postId, a post summary, assignees, candidates, revision, supportedCurrentAssignment and inputLimits, with writesPerformed:false. Candidate records contain profileId, role and identity; optional profile.id must equal profileId. Roles are numeric SELLER=0, DELEGATEE=1 and CREATOR=2. Display names/images are presentation data, not selection keys. The bridge retains unknown candidate JSON fields for the eventual source request; callers send only profileId.
Each list is bounded to 1,000 distinct profile IDs and the complete snapshot to 4 MiB. These are bridge limits, not inferred service capacities. Duplicate IDs, explicit foreign identities and contradictory projections fail closed. Multiple current assignees can be returned with supportedCurrentAssignment:false; the writer refuses to silently remove extra people. An empty current list is valid, but an empty candidate list provides no eligible selection.
The dedicated revision binds the verified context, semantic post state, current assignees and complete candidate contents; candidates are compared in profile-ID order. It is not the ordinary post detail, selection or conversion revision. The writer takes another matching snapshot before sending. Unknown non-counter post fields participate in preservation; generated update time and existing interaction counters retain their ordinary exclusions. Sequential reads are not atomic.
Use the returned revision and one discovered profileId for [assignment](content_post_apply.md#change-an-original-article-assignee). The fresh read opens the exact original post detail; it does not open a person selector with a candidate preselected. No task is created, no pending marker is cleared and no actual assignment, notification, console rendering or visitor access is established.
### Complete assignee discovery example
Replace the channel and post ID with observed values. This is an input illustration, not a recorded service call.
```json
{
"channelCode": "channel98",
"pAppCode": "B00001",
"view": {
"kind": "article_assignee",
"postId": 7
}
}
```
## Source conversion projection and hosted persistence
The original seller post API embeds a conversion object without its numeric id.
The reader verifies its known fields against the dedicated link and exact post;
a conflicting object never means absent. New source-conversion-v1 write journals
permit that verified projection to follow initialization/editing while preserving
all other post values and unknown fields. Existing journals retain their earlier
strict comparison and observation-only retry. The workflow writes its pending
guard through the same store instance holding the hosted lock. See the
[backend contract correction](../papp-content/article-conversion.md).
Timeline STORY responses may have title:null because the original form has no title field. This exact stored value is preserved; no title is fabricated.
## Timeline video candidate and result reads
For exact A00001/A9xx01 OWNER, use `view.kind:timeline_video_creation` with an
acknowledged `uploadTaskId` from `content_file_upload` purpose `timeline_video`.
This reads the canonical upload record, current channel actor, installed label
requirement, complete existing labels and POST catalogs through existing common
readers. It returns the revision required by `timeline_video_create`. Catalog
choices use string `ccid` business identities, while labels use numeric IDs.
The preparation does not create a candidate or request another upload.
`view.kind:timeline_video_candidates` accepts query `{page,limit,recentDays?}`
and reads one bounded candidate page. Its identity/state is an encoding record;
WAITING or POSTED supplies no final post ID and proves neither a saved post nor
playback. The console link opens the exact Timeline posts list as a parent;
this source exposes no Timeline candidate manager screen.
`view.kind:timeline_video_result` takes an existing candidate `taskId` plus a
`postId` explicitly selected from the normal post list. It independently checks
that post's exact consumer and VIDEO representation, compares its text, author,
publication, labels and catalog choices, and returns the normal detail revision.
It never infers the post from title, newest-list order or a candidate status.
Even matching fields retain `candidateToPostLinkVerified:false` and
`playbackVerified:false`. The exact selected-post console link supports a separate
human playback inspection; the read itself is not that inspection.