Integrations

    Custom publishing webhook

    Send structured article HTML to your own site or automation.

    Use a custom webhook for a CMS or workflow that is not a direct publishing destination. The receiver is responsible for creating the content and respecting the requested mode.

    Set up the receiver

    1. Create a webhook trigger in Make, Zapier, n8n or your backend. Copy its public HTTPS URL and keep it private.
    2. Add a CMS action that creates a draft or live article according to is_draft. Map the fields below, including the cover if your site uses one.
    3. Open Plan → Schedule and publishing → Connect or manage a website → Custom website, or choose Custom website during onboarding.
    4. Paste the URL and choose Save Settings.
    5. Put your workflow into its listening or test mode, then choose Test Connection in outwrite.ai. This sends a sample marked as a draft.
    6. Check the workflow and CMS to confirm the sample arrived as a draft, with the right fields. Enable the receiver for future requests.

    Treat the webhook URL as a credential. Validate incoming requests and do not expose the URL in public source code. Testing sends real data to your receiver, so configure draft handling before pressing the test button.

    Core payload

    {
      "title": "How to evaluate your next tool",
      "content": "<h1>How to evaluate your next tool</h1><p>Article HTML.</p>",
      "slug": "evaluate-your-next-tool",
      "content_type": "raw",
      "source": "outwrite.ai",
      "is_draft": true,
      "operation_id": "unique-operation-id",
      "revision": 1
    }
    

    The payload also includes an excerpt, word count and available content metadata. Image, author and meta-description fields may be null. Do not make them required unless your receiver supplies an appropriate default.

    published_at is the operation timestamp. It is not proof that the article is live. is_draft describes the requested destination state.

    Preserve the content

    Map HTML into a rich-text or HTML field. Preserve headings, lists, tables, citation URLs and internal links. Do not strip structure into plain text or independently rewrite a checked article.

    Make delivery idempotent

    Store operation_id alongside the remote record. If the same operation arrives again, return the existing result instead of creating another page.

    A 2xx response confirms receipt, not necessarily publication. Distinguish accepted work, a saved remote draft and a live page. Do not report published before the page exists in the intended state.

    Confirm the final page

    Article deliveries include a publication_receipt object with a callback URL, a scoped token and authorization type. Connection-test payloads do not include a publication receipt. Treat the token as a secret and never include it in the article or a public log.

    For asynchronous delivery, POST a JSON receipt to the supplied URL with Authorization: Bearer <publication_receipt.token>. The token is scoped to that operation and expires seven days after the operation was created. Use the URL supplied in the payload rather than hard-coding a deployment hostname.

    {
      "operation_id": "the-original-operation-uuid",
      "revision": 1,
      "content_hash": "64-character-lowercase-sha256-hex",
      "remote_id": "your-cms-record-id",
      "status": "remote_draft"
    }
    

    Calculate content_hash from the exact received title, a null byte, and the exact received HTML content, in that order. For example, in Node.js:

    import { createHash } from "node:crypto";
    const contentHash = createHash("sha256")
      .update(`${payload.title}\0${payload.content}`)
      .digest("hex");
    

    Use remote_draft only for a requested draft. For a requested live publication, use published and include the final public url. A published receipt is checked for accessibility before it becomes a verified publication. A private or unavailable page can remain awaiting confirmation. The JSON body must be no larger than 8 KB.

    For a synchronous receiver, return those same fields in the original successful response. A plain 2xx response without matching operation, revision and content hash remains acceptance only.

    The callback returns 401 for invalid or expired authorization, 400 for malformed receipt data, and 409 when the operation, content or destination cannot be verified. Repeating an already accepted final receipt is safe. A 409 is not a request to create another CMS article.

    If a send is unconfirmed, inspect your receiver logs and the remote CMS before asking outwrite.ai to retry.

    Choose it in Plan

    After connecting, select the webhook destination in Schedule and publishing, confirm Draft or Publish, and test an end-to-end draft before relying on automation.

    Featured image fields

    featured_image_url contains the selected cover URL and featured_image_alt its description. featured_image_credit contains the photographer's name, profile URL and original photo URL. Map these to your CMS image fields. When the author removes a cover, all three fields are null. The HTML also includes a short photographer credit for selected covers.

    Need a hand with your workspace?Get help