> ## Documentation Index
> Fetch the complete documentation index at: https://api-docs.hrizn.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Mark content as externally posted

> Report the live URL after your integration publishes Hrizn content

After your integration publishes content to an external content management system (CMS) or website, call `POST /v1/public/content/{id}/posted` to record its URL in Hrizn.

**Authentication required:** `X-API-Key`

**Scope required:** `content:write`

**Plan entitlement required:** API Access (`API_ACCESS`)

The API key's associated site constrains both the content lookup and the conditional write. Missing content and content belonging to another site return the same `404 not_found`. Authorization is checked again on every request, including retries.

## Verify the saved state

Call `GET /v1/public/content/{id}` with `content:read` on the same site's key. Its `publishing` object returns `posted_url`, `marked_posted_at`, and `publish_state`, alongside the unchanged `canonical_url`. The top-level `status` still describes generation. Hrizn's existing content UI reflects the saved marker and URL on normal refetch or reopening the content.

## Path parameters

<ParamField path="id" type="string" required>
  The Hrizn content UUID returned when you created the content. Keep this ID alongside the external URL in your integration. An external CMS ID, job ID, or IdeaCloud ID is not a content ID.
</ParamField>

## Request body

<ParamField body="posted_url" type="string" required>
  An absolute HTTP or HTTPS URL with no embedded credentials. Hrizn trims surrounding whitespace before validation; the trimmed URL must be at most 4096 characters.
</ParamField>

The body accepts **only** `posted_url`. Unknown fields are rejected. Send no site, customer, actor, external publication timestamp, or event-version fields; tenant scope and attribution come from the authenticated request.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl -X POST https://api.app.hrizn.io/v1/public/content/b50febaf-657a-4f6a-b951-2898aa079865/posted \
  -H "X-API-Key: hzk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"posted_url":"https://www.example.com/blog/hybrid-suv-guide"}'
```

## Response

<ResponseExample>
  ```json 200 theme={"theme":{"light":"github-light","dark":"github-dark"}}
  {
    "data": {
      "id": "b50febaf-657a-4f6a-b951-2898aa079865",
      "posted_url": "https://www.example.com/blog/hybrid-suv-guide",
      "marked_posted_at": "2026-09-11T15:00:00.000Z",
      "publish_state": "published"
    }
  }
  ```
</ResponseExample>

`marked_posted_at` is the time the server first recorded the report, not an independently verified publication date or a timestamp supplied by your CMS. URL corrections preserve this time. `publish_state: "published"` acknowledges the recorded external publication report.

## Retries and URL corrections

* A retry with the current URL is a no-op and preserves the first marked time.
* A different URL replaces the recorded URL and preserves the first marked time.
* The last successfully applied update wins. There is no event version or ordering based on the CMS publication date.
* Serialize URL corrections for each content ID and stop retrying superseded URLs. An old retry submitted after a correction can otherwise replace the correction.
* For `409 conflict` caused by concurrent update contention, retry only the latest intended payload.

<Warning>
  This endpoint does not support response caching through `X-Idempotency-Key`. Its same-current-URL no-op behavior is separate from the [idempotency-key contract](/concepts/idempotency). Every call re-runs authorization.
</Warning>

## What this callback records

Hrizn reuses the existing `manual` posted marker and stores the reported URL. The callback does not crawl or independently verify the page, perform publishing, change generation state, change CMS publishing state, or modify telemetry.

<Note>
  Recording an external publication does not add the item to the integrated [published-content feed](/api-reference/content/list-published) or unlock [publish-data](/api-reference/content/get-publish-data). Those endpoints retain their existing CMS publishing requirements.
</Note>

## Backfill existing publications

Use your integration's known Hrizn content-ID/URL pairs and send one request per pair. The server records when each report is received, rather than backdating it to the original publication. This callback provides no scanning, batch, or unpublish operation, and adds no MCP tools.

## Errors

* `400 validation_error`: invalid content UUID, invalid URL, or unknown body fields.
* `401`: missing or invalid API key.
* `403 forbidden`: the API key lacks `content:write`.
* `403 plan_upgrade_required`: the key-associated site lacks the `API_ACCESS` entitlement.
* `404 not_found`: missing content or content belonging to another site; the responses are indistinguishable.
* `409 conflict`: concurrent update contention; retry the latest intended payload.
* `429`: rate limit exceeded; follow the [rate-limit guidance](/rate-limiting).
* `503 service_unavailable`: publication recording is temporarily unavailable.
* `500`: unexpected internal server error.

Failures use the standard [error envelope](/concepts/errors). A reported URL is not proof that a page is live; keep publication verification in your integration.


## OpenAPI

````yaml POST /content/{id}/posted
openapi: 3.1.0
info:
  title: Hrizn Public API
  version: 1.2.0
  description: >
    The Hrizn Public API allows partners to programmatically create content,
    manage inventory descriptions, and integrate with the Hrizn platform.


    All endpoints are prefixed with `/public` and require an API key passed via
    the `X-API-Key` header (except the health check).
  contact:
    email: support@hrizn.io
servers:
  - url: https://api.app.hrizn.io/v1/public
    description: Production
security:
  - apiKeyAuth: []
tags:
  - name: Analytics
    description: >-
      Warehoused Google Search Console and GA4 reads (Teams+ API access,
      analytics:read). URL Inspection is live only on pages/performance.
  - name: IdeaClouds
    description: Create and manage AI-powered keyword research
  - name: Content Intelligence
    description: AI-powered content gap analysis and recommendations
  - name: Content
    description: Generate content from IdeaClouds
  - name: Compliance
    description: Run OEM compliance checks on content
  - name: Content Tools
    description: Generate SEO metadata, schemas, and social snippets
  - name: Inventory
    description: Access vehicle data and AI descriptions
  - name: Images
    description: >-
      Media Library images. Read the library (images:read): list and fetch
      images with alt text, AI-written title/caption/description, the generating
      prompt, dimensions, article links, and social variant cuts. Generate
      (images:write): async AI image generation returning an image_id;
      completion is delivered via image.generation.completed /
      image.generation.failed webhooks.
  - name: Market
    description: >-
      Live local market listings, days supply, competitive set, and pricing
      insights (Unlimited plan + market_data:read)
  - name: Site
    description: View dealership details and configuration
  - name: Webhooks
    description: Manage webhook subscriptions for real-time events
  - name: Reference
    description: Look up available types, scopes, and events
  - name: Social
    description: >-
      Social Hub posting and reviews across all connected platforms (X,
      Facebook, Instagram, LinkedIn, Google Business Profile)
  - name: Health
    description: Health check (no authentication)
  - name: Share
    description: >-
      Anonymous share-page routes (no API key). Called by Hrizn share pages
      (/s/{publicId}) on behalf of shoppers who are not signed in. Requests must
      originate from the Hrizn app origin (CORS is origin-checked, never
      wildcard) and are rate limited per client IP. Responses use a flat `{
      error }` / `{ success }` body, not the `{ error: { code, message } }`
      envelope of API-key routes.
paths:
  /content/{id}/posted:
    post:
      tags:
        - Content
      summary: Mark content as externally posted
      description: >
        Report where your integration already published a Hrizn content item.

        Requires X-API-Key, content:write, and the API_ACCESS plan entitlement.

        The key-associated site constrains both reads and conditional writes;

        missing content and content belonging to another site return the same
        404.

        Only posted_url is accepted; site, customer, and actor IDs are never
        accepted.


        This records the existing manual posted marker and URL, without
        crawling,

        independently verifying, or publishing the page. Generation state, CMS

        publishing state, and telemetry are unchanged. This callback does not
        add

        content to /content/published or make /content/{id}/publish-data
        available.


        marked_posted_at is the server-recorded first report time, not an
        external

        publication date. Corrections preserve it. Retrying the current URL is a

        no-op; a different URL replaces it. The last successfully applied update

        wins. Serialize corrections per content ID and stop superseded retries;

        there is no event version. On contention (409), retry only the latest
        payload.

        X-Idempotency-Key response caching is not supported; authorization
        reruns

        on every call. Backfill known content-ID/URL pairs one request at a
        time;

        no scanning, batch, unpublish, or new MCP tool is provided.
      operationId: markContentPosted
      parameters:
        - name: id
          in: path
          required: true
          description: >-
            Hrizn content UUID returned by create; never an external CMS, job,
            or IdeaCloud ID.
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              required:
                - posted_url
              properties:
                posted_url:
                  type: string
                  format: uri
                  maxLength: 4096
                  description: >-
                    Absolute HTTP(S) URL with no embedded credentials.
                    Surrounding whitespace is trimmed before validation; the
                    trimmed URL must be at most 4096 characters.
                  example: https://www.example.com/blog/hybrid-suv-guide
      responses:
        '200':
          description: External publication recorded, corrected, or already current
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    type: object
                    required:
                      - id
                      - posted_url
                      - marked_posted_at
                      - publish_state
                    properties:
                      id:
                        type: string
                        format: uuid
                      posted_url:
                        type: string
                        format: uri
                      marked_posted_at:
                        type: string
                        format: date-time
                        description: >-
                          Server-recorded first report time; preserved on
                          retries and URL corrections.
                      publish_state:
                        type: string
                        enum:
                          - published
        '400':
          description: >-
            validation_error — invalid content UUID, invalid posted_url, or
            unknown body fields
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: >-
            forbidden for missing content:write scope, or plan_upgrade_required
            for missing API_ACCESS entitlement
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: >-
            not_found — content is missing or belongs to another site; responses
            are indistinguishable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: >-
            conflict — concurrent update contention; retry only the latest
            intended posted_url payload
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          description: >-
            service_unavailable — publication recording is temporarily
            unavailable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - apiKeyAuth: []
components:
  schemas:
    ErrorResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              example: validation_error
            message:
              type: string
              example: 'keyword: Required'
            details:
              type: object
            request_id:
              type: string
  responses:
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    RateLimited:
      description: Rate limit exceeded
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    InternalError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: Your Hrizn API key (prefix hzk_)

````