Docs
Social

Create a social post

POSThttps://api.norreach.app/v1/social/posts

Creates a post (a draft by default) with your own text and media, one version per network — through the app's social calendar, exactly as the composer saves. Nothing goes out: schedule it with POST /social/posts/{id}/schedule. Media: public http(s) addresses, or upload a file first with POST /social/uploads; a file in another workspace's media is refused (422). Each network's character limit and Instagram's need for a picture are checked when scheduling. Posts carry your own text, pictures and videos — there is no operation that writes posts with AI (Nora writes posts in a plan: POST /briefs). Owners, admins and managers.

⚠ social:publishRole must allow: social.publishOperation id: create_social_post
POST/social/posts
curl -X POST "https://api.norreach.app/v1/social/posts" \
  -H "Authorization: Bearer $NORREACH_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "title": "Winter staffing",
  "labels": [
    "winter"
  ],
  "variants": [
    {
      "network": "linkedin",
      "content": "Clinics plan their winter staffing now. We place licensed nurses within 48 hours."
    },
    {
      "network": "instagram",
      "content": "Winter is coming — so are our nurses.",
      "media_urls": [
        "https://media.example.com/social-media/6a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d/2f3e4d5c-6b7a-4c8d-9e0f-1a2b3c4d5e6f.jpg"
      ]
    }
  ]
}'
Create a social post
{
  "id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
  "object": "social_post",
  "title": "Winter staffing",
  "status": "draft",
  "scheduled_at": null,
  "timezone": null,
  "labels": [
    "winter"
  ],
  "notes": "",
  "networks": [
    "linkedin",
    "instagram"
  ],
  "variants": [
    {
      "network": "linkedin",
      "network_name": "LinkedIn",
      "content": "Clinics plan their winter staffing now. We place licensed nurses within 48 hours.",
      "media_urls": [],
      "status": "pending",
      "published_at": null,
      "problem": null
    },
    {
      "network": "instagram",
      "network_name": "Instagram",
      "content": "Winter is coming — so are our nurses.",
      "media_urls": [
        "https://media.example.com/social-media/6a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d/2f3e4d5c-6b7a-4c8d-9e0f-1a2b3c4d5e6f.jpg"
      ],
      "status": "pending",
      "published_at": null,
      "problem": null
    }
  ],
  "created_at": "2026-11-05T09:12:33.120Z",
  "updated_at": "2026-11-05T09:20:01.000Z"
}

Authorizations

Authorizationstringheaderrequired

Bearer authentication: send Authorization: Bearer <key>, with an API key or an OAuth access token. The key needs the scope social:publish. API keys and scopes

Headers

Idempotency-Keystringheader

Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.

Body

application/json

titlestring

The post's name in the calendar (never published).

statusenum

idea, draft (default) or in_review — scheduling has its own operation.

One of:ideadraftin_review
labelsstring[]
notesstring

Internal notes (never published).

variantsobject[]

One version per network, with your own text and media.

Show child attributes
variants[].networkenumrequired

linkedin, x, instagram, facebook or tiktok.

One of:linkedinxinstagramfacebooktiktok
variants[].contentstring

The text for this network (each network's own limit is checked when scheduling: X 280, LinkedIn 3000, Instagram 2200, Facebook 5000, TikTok 2200).

variants[].media_urlsstring[]

Up to 10 pictures or videos. Instagram needs at least one to be scheduled.

Response

201application/json— Create a social post

idstring (uuid)required

An id (UUID).

object"social_post"required
titlestringrequired

The post's name in the calendar (never published).

statusenumrequired

idea, draft, in_review, scheduled, publishing, published or failed.

One of:ideadraftin_reviewscheduledpublishingpublishedfailed
scheduled_atstring | nullrequired

When it goes out (scheduled posts).

timezonestring | nullrequired

The IANA time zone it was scheduled in, for display.

labelsstring[]required
notesstringrequired

Internal notes (never published).

networksenum[]required
variantsobject[]required
Show child attributes
variants[].networkenumrequired

linkedin, x, instagram, facebook or tiktok.

One of:linkedinxinstagramfacebooktiktok
variants[].network_namestringrequired
variants[].contentstringrequired

The text for this network.

variants[].media_urlsstring[]required

Pictures and videos, in order (public https addresses).

variants[].statusenumrequired

pending (not sent yet), publishing, published or failed.

One of:pendingpublishingpublishedfailed
variants[].published_atstring | nullrequired
variants[].problemstring | nullrequired

When this network's publish failed: a plain sentence (the details are in the app).

created_atstringrequired

RFC 3339 UTC timestamp with milliseconds.

updated_atstringrequired

RFC 3339 UTC timestamp with milliseconds.

Errors

Errors are application/problem+json with a stable code.

StatusCodeMeaning
400bad_requestThe request couldn't be read.
400unknown_fieldThe request has a field this operation doesn't know.
401unauthorizedA valid API key is required.
403insufficient_scopeThis API key doesn't have the scope this operation needs.
403feature_not_enabledThe API isn't switched on for this workspace.
403role_forbiddenThe key's creator's role can't do this.
409idempotency_in_progressA request with this Idempotency-Key is still running.
409conflictThat conflicts with the current state.
413too_largeThe request body is too large.
422validation_failedThe request has invalid fields.
422idempotency_mismatchThis Idempotency-Key was used with a different request.
429rate_limitedToo many requests. Slow down and try again.
500server_errorSomething went wrong on our side.
503unavailableThe API isn't available right now. Try again shortly.