API reference

POST/v1/posts/validate

Validate a post

Dry-runs the same validation as create, without writing anything. Use it to show errors in your own UI before submitting.

Required permission: `posts:write`

Accepts `profileId` to target a specific profile. Omit it to use the key’s home profile.

Base URL
https://api.cutedyno.com
Permission
posts:write
Idempotency
Not applicable. This request has no side effects worth deduplicating.
MCP tool
validate_post

Request

curl -X POST "https://api.cutedyno.com/v1/posts/validate" \
  -H "Authorization: Bearer $CUTEDYNO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "profileId": "profile_a1b2c3d4",
  "content": "Shipping today.",
  "media": [
    {
      "type": "image",
      "url": "https://cdn.example.com/media/launch.jpg"
    }
  ],
  "accountIds": [
    "string"
  ],
  "scheduledAt": "string",
  "publishNow": false,
  "platforms": {
    "facebook": {
      "privacy": {
        "value": "PUBLIC"
      },
      "place": "string",
      "alt_text_custom": "string",
      "no_story": false
    },
    "instagram": {
      "location_id": "location_id_a1b2c3d4",
      "thumbnail_url": "https://cdn.example.com/media/launch.jpg",
      "collaborators": [
        "string"
      ]
    },
    "tiktok": {
      "title": "string",
      "privacy_level": "PUBLIC_TO_EVERYONE",
      "disable_comment": false,
      "disable_duet": false,
      "disable_stitch": false,
      "video_cover_timestamp_ms": 0,
      "brand_content_toggle": false,
      "brand_organic_toggle": false,
      "is_aigc": false,
      "auto_add_music": false,
      "upload_as_draft": false
    },
    "linkedin": {
      "title": "string",
      "visibility": "PUBLIC"
    },
    "youtube": {
      "title": "string",
      "description": "string",
      "privacyStatus": "public",
      "tags": [
        "string"
      ]
    }
  },
  "approvers": [
    "string"
  ]
}'

Body

profileIdstringoptional

Profile to act on. Defaults to the profile the API key was created in.

contentstringoptional

Post text. Used as the caption for image and video posts. Required unless the post is a draft with media.

MediaItem[]optional

Images or a single video. Get URLs from POST /v1/media/upload. Content type is inferred: a video wins, otherwise images, otherwise text.

accountIdsstring[]optional

`id` values from GET /v1/accounts; `platformAccountId` also works. Required to schedule or publish, omit to save an unassigned draft.

scheduledAtstringoptional

ISO 8601 datetime, for example 2026-08-01T12:00:00Z.

publishNowbooleanoptional

Queue for immediate publishing. Cannot be combined with scheduledAt.

objectoptional

Per-platform options, applied only to accounts on that platform. Everything here is optional; sensible defaults apply.

approversstring[]optional

Emails to send approval requests to, used only when the profile or key requires approval. Defaults to the key owner.

Response

Returns 200 with the following body.

validbooleanrequired
dryRunbooleanoptional
warningsstring[]optional
object[]optional
objectoptional

Example

{
  "valid": false,
  "dryRun": false,
  "warnings": [
    "string"
  ],
  "errors": [
    {
      "code": "string",
      "message": "Shipping today."
    }
  ],
  "normalized": {
    "profileId": "profile_a1b2c3d4",
    "contentType": "text",
    "accountCount": 0,
    "scheduledAt": "string",
    "mode": "draft"
  }
}

Errors

Failures use the standard error envelope. Branch on code, never on the message.

StatusCodeWhen it happens
400invalid_requestThe request body or query string failed validation. The message names the offending field.
401invalid_api_keyThe key does not exist, was revoked, or is malformed. Keys start with cdyn_live_.
403profile_not_accessibleThe requested profile is outside this key’s scope, or belongs to another account.
429rate_limit_exceededToo many requests for this key. Honour the Retry-After header before retrying.
500internal_errorSomething failed on our side. Retry with the same Idempotency-Key; report the requestId if it persists.