Adopt social content

social.outputs.adopt@1

Saves a draft post for each account you choose, from a caption you give or the result of an automation. Drafts are never approved, dated or published by this call. It needs a key with Write social.

Save a draft for an account

Replace YOUR_ACCOUNT_ID with an account's id.

# A new operationId for each new request; the same one to retry it.
curl https://api.growlocal.site/api/v1/profiles/YOUR_BUSINESS_ID/invocations \
  -H "Authorization: Bearer gl_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "target": {
    "featureId": "YOUR_FEATURE_ID",
    "export": "adoptOutputs",
    "contractRef": "social.outputs.adopt@1"
  },
  "operationId": "adopt-post-1",
  "input": {
    "accountRefs": [
      {
        "businessProfileId": "YOUR_BUSINESS_ID",
        "featureId": "juniper-cakes.social",
        "collectionId": "juniper-cakes.accounts",
        "id": "YOUR_ACCOUNT_ID"
      }
    ],
    "caption": "This week: lemon drizzle, fresh from the oven.",
    "mediaRefs": [],
    "format": "post"
  }
}'
// A new operationId for each new request; the same one to retry it.
const response = await fetch(
  "https://api.growlocal.site/api/v1/profiles/YOUR_BUSINESS_ID/invocations",
  {
    method: "POST",
    headers: {
      Authorization: "Bearer gl_YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      "target": {
        "featureId": "YOUR_FEATURE_ID",
        "export": "adoptOutputs",
        "contractRef": "social.outputs.adopt@1"
      },
      "operationId": "adopt-post-1",
      "input": {
        "accountRefs": [
          {
            "businessProfileId": "YOUR_BUSINESS_ID",
            "featureId": "juniper-cakes.social",
            "collectionId": "juniper-cakes.accounts",
            "id": "YOUR_ACCOUNT_ID"
          }
        ],
        "caption": "This week: lemon drizzle, fresh from the oven.",
        "mediaRefs": [],
        "format": "post"
      }
    }),
  },
);
const receipt = await response.json();
console.log(response.status, receipt);
import requests

# A new operationId for each new request; the same one to retry it.
response = requests.post(
    "https://api.growlocal.site/api/v1/profiles/YOUR_BUSINESS_ID/invocations",
    headers={"Authorization": "Bearer gl_YOUR_API_KEY"},
    json={
        "target": {
            "featureId": "YOUR_FEATURE_ID",
            "export": "adoptOutputs",
            "contractRef": "social.outputs.adopt@1",
        },
        "operationId": "adopt-post-1",
        "input": {
            "accountRefs": [
                {
                    "businessProfileId": "YOUR_BUSINESS_ID",
                    "featureId": "juniper-cakes.social",
                    "collectionId": "juniper-cakes.accounts",
                    "id": "YOUR_ACCOUNT_ID",
                },
            ],
            "caption": "This week: lemon drizzle, fresh from the oven.",
            "mediaRefs": [],
            "format": "post",
        },
    },
    timeout=30,
)
print(response.status_code, response.json())

Parameters

What goes in input:

Name Type Required Description
source object No Where the content came from, when it is an automation's result. Leave it out for content you wrote.
source.featureId string Yes The feature the run belongs to.
source.runRef string Yes The run that made the content.
source.itemKey string Yes The result's key within that run.
accountRefs array of object Yes The accounts to write for, 1 to 10, one post version each; one listed twice is refused.
accountRefs[].businessProfileId string Yes Your business's id.
accountRefs[].featureId string Yes The featureId of the account's row.
accountRefs[].collectionId string Yes The collectionId of the account's row.
accountRefs[].id string Yes The account's id.
caption string Yes The caption for each new post version. Refused if longer than an account's platform allows.
mediaRefs array of string Yes Photos and videos from Drive, in order, by reference; an empty list for none. For an automation's result they must be exactly the media it produced.
format one of post, story, reel Yes post, story or reel. Stories and reels need media, and an automation's result can only be adopted as a post.
platformOptions object No Settings for the platform, such as link or privacy; only those the account's platform takes (Read post destinations).
platformOptions.altText string No A text description of the picture.
platformOptions.link string No A link to attach.
platformOptions.firstComment string No A first comment to add.
platformOptions.title string No A title, for platforms that have one.
platformOptions.privacy one of public, unlisted, private No public, unlisted or private.
platformOptions.shareToFeed boolean No Also share to the feed.
platformOptions.collaborators array of string No Accounts to credit as collaborators.
platformOptions.allowComments boolean No Whether people may comment.
platformOptions.allowDuet boolean No Whether others may make a duet.
platformOptions.allowStitch boolean No Whether others may stitch it.
platformOptions.discloseBrand boolean No Marks the post as promoting a brand.
platformOptions.brandedContent boolean No Marks the post as paid brand content.
platformOptions.aiGenerated boolean No Marks the post as made with AI.
platformOptions.madeForKids boolean No Marks the video as made for children.
platformOptions.replySettings one of everyone, following, mentionedUsers, subscribers, verified No Who may reply: everyone, following, mentionedUsers, subscribers or verified.
notes string No Notes kept with each new post version, never posted. Empty when left out.
contentItemRef object No Groups the new versions under one content item.
contentItemRef.businessProfileId string Yes Your business's id.
contentItemRef.featureId string Yes The featureId of the row.
contentItemRef.collectionId string Yes The collectionId of the row.
contentItemRef.id string Yes The row's id.

Response

A call that worked answers 200 with an applied receipt; its output holds these fields, among others. GET /catalog/social.outputs.adopt@1 answers the complete shape as JSON Schema.

Name Type Description
editions array of object The post versions created, one per account.
editions[].ref object The version's reference.
editions[].revision integer Its revision.
editions[].account object The account it is for.
editions[].account.label string The account's name.
editions[].account.platform one of facebook, instagram, linkedin, x, tiktok, youtube, pinterest, threads, bluesky Its platform.
editions[].account.handle string Its handle on the platform.
editions[].account.connected boolean Whether the account is still connected.
editions[].account.textPost object Whether this platform accepts a text-only post, independently of whether the account is connected.
editions[].account.textPost.compatible boolean True when the connector accepts a post with no media.
editions[].account.textPost.reason string The plain reason when text-only posting is incompatible; omitted otherwise.
editions[].caption string The caption.
editions[].mediaRefs array of string The media, in order.
editions[].format one of post, story, reel post, story or reel.
editions[].notes string The internal notes.
editions[].source object or null Where the content came from, or null.
editions[].createdAt string When it was made.
editions[].createdBy string or null Who made it, or null.
editions[].approval object Whether the version is approved. A new version is not.
editions[].approval.state one of none, approved, invalidated none, approved or invalidated.
editions[].status one of draft, approved, scheduled, suspended, held, dispatching, accepted, published, failed, uncertain Where the version is. A new one is draft: it is never scheduled or published here.
editions[].canEdit boolean Whether you may edit it.
editions[].canApprove boolean Whether you may approve it.
editions[].canSchedule boolean Whether you may schedule it.
editions[].canCancel boolean Whether you may cancel it.
editions[].canRemove boolean Whether you may remove it.
{
  "status": "applied",
  "operationId": "adopt-post-1",
  "output": {
    "editions": [
      {
        "ref": {
          "businessProfileId": "YOUR_BUSINESS_ID",
          "featureId": "juniper-cakes.social",
          "collectionId": "juniper-cakes.editions",
          "id": "YOUR_EDITION_ID"
        },
        "revision": 1,
        "account": {
          "ref": {
            "businessProfileId": "YOUR_BUSINESS_ID",
            "featureId": "juniper-cakes.social",
            "collectionId": "juniper-cakes.accounts",
            "id": "YOUR_ACCOUNT_ID"
          },
          "revision": 1,
          "label": "Juniper Cakes",
          "platform": "x",
          "handle": "junipercakes",
          "connected": true,
          "textPost": {
            "compatible": true
          },
          "constraints": null
        },
        "caption": "This week: lemon drizzle, fresh from the oven.",
        "mediaRefs": [],
        "format": "post",
        "platformOptions": {},
        "notes": "",
        "source": null,
        "createdAt": "2026-11-13T09:30:00Z",
        "createdBy": null,
        "contentDigest": "0000000000000000000000000000000000000000000000000000000000000000",
        "approval": {
          "state": "none",
          "digest": null,
          "approvedAt": null,
          "approvedBy": null,
          "review": null
        },
        "publication": null,
        "status": "draft",
        "canEdit": true,
        "canApprove": true,
        "canSchedule": false,
        "canCancel": false,
        "canRemove": true
      }
    ]
  }
}

Errors

Besides the answers every request can get (Errors), its receipt can say:

Status HTTP What it means
pending 202 Accepted and still running. Look it up with GET /operations/{operationId}.
uncertain 202 GrowLocal can't yet tell whether it took effect. Look it up before trying again.
requirements 409 Something must happen first; the receipt lists what.
conflict 409 The row changed since you read it, or this operationId was used with a different body.
rejected 400, or 403 when it's a matter of access Not done. diagnostics says why: each has a code, a path into what you sent and a message.

The codes in diagnostics you're most likely to see:

Code Status What it means
SOCIAL.CAPTION_TOO_LONG rejected The caption is longer than an account's platform allows.
SOCIAL.FORMAT_NEEDS_MEDIA rejected A story or reel has no media.
SOCIAL.SOURCE_MEDIA_MISMATCH rejected With a source, mediaRefs are not exactly the media the automation produced.
SOCIAL.SOURCE_NOT_FOUND rejected No such run for this business.
SOCIAL.SOURCE_NOT_SETTLED rejected The run has not finished yet.
SOCIAL.ACCOUNT_DUPLICATE rejected An account is listed twice.
SOCIAL.PLATFORM_UNSUPPORTED rejected An account's platform cannot be published to.