# SosoAPI-publicatie-API: authenticatie, verzoeken en resultaten

Canonieke URL: https://sosoapi.ai/nl/docs/publishing-api-reference

Bouw een publicatie-integratie op je server rond één Scheduled Post per bestemming. Dit naslagwerk beschrijft het publicatie-API-contract dat op 20 oktober 2026 is beoordeeld. Voorbeelden bevatten placeholders en worden niet op deze pagina uitgevoerd.

## 1. Authenticeer vanaf je server

Maak een API-sleutel in SosoAPI App → Settings → Agents & API Access. Bewaar die als SOSOAPI_API_KEY in je serveromgeving. Verzoeken gebruiken Authorization: Bearer <your-key> en Content-Type: application/json. Neem de sleutel nooit op in een website, mobiele appbundel, URL of openbare repository.

Alle onderstaande endpoints gebruiken POST met een JSON-body. Sleutels en gedelegeerde agentmachtigingen worden beperkt door bevoegdheden, toegestane werkruimten en het huidige lidmaatschap van de eigenaar. Leesacties vereisen agent:operate en minimaal viewer-toegang; publicatiewijzigingen vereisen agent:publish en minimaal editor-toegang. Een machtiging kan de rechten van de eigenaar niet verruimen.

Gebruik de huidige werkruimte en verbonden accounts van de app, of roep /identity-api/workspace/list en /identity-api/user/social-accounts/list aan om IDs te vinden die je mag gebruiken. Raad nooit de werkruimte- of account-ID van een klant.

```
// Node.js 20+; run only on your server.
const apiKey = process.env.SOSOAPI_API_KEY;
if (!apiKey) throw new Error("Set SOSOAPI_API_KEY on your server");
const apiBase = "https://gqeshlawtcexsapabaui.supabase.co/functions/v1";

async function sosoPost(path, body) {
  const response = await fetch(apiBase + path, {
    method: "POST",
    headers: {
      Authorization: "Bearer " + apiKey,
      "Content-Type": "application/json"
    },
    body: JSON.stringify(body)
  });
  const result = await response.json();
  if (!response.ok) {
    const requestId = result.request_id ?? response.headers.get("x-request-id");
    // Handler errors use code/message; schema-validation 400s instead use
    // success:false and error:{name:"ZodError",message:...}.
    // Preserve status, available code and requestId in server diagnostics.
    // Never log the key or an Authorization header.
    throw new Error("SosoAPI " + response.status + " (" +
      (requestId ?? "no request id") + ")");
  }
  return result;
}
```

## 2. Overzicht van publicatie-endpoints

Deze paden zijn relatief aan de API-basis van de serverhelper. Haal het Scheduled Post-detail op voor de huidige versie, beschikbare acties en het publicatieresultaat.

Scheduled Posts-endpoints; elk verzoek is POST

| Pad | Verzoek | Antwoord en grens |

| --- | --- | --- |

| /studio-api/scheduled-posts/list | workspace_id; optioneel project_id, status, tijdpaar, limit, cursor. | posts, next_cursor, returned_count. Leesactie binnen de werkruimte. |

| /studio-api/scheduled-posts/get | id. | post, delivery, actions, attempts, outcomes. Lees hier de huidige versie. |

| /studio-api/scheduled-posts/eligibility | workspace_id, targets; optioneel include_quota. | destinations en optionele quota. Voorafgaande leescontrole, geen reservering. |

| /studio-api/scheduled-posts/create | workspace_id, exact account, provider_payload, content, scheduled_at, idempotency_key. | post en deduped. 201 voor een nieuwe planning; 200 voor een overeenkomende herhaling. |

| /studio-api/scheduled-posts/bulk-create | workspace_id en 1–50 targets, elk met een eigen idempotency_key. | batch_id, successes, failures. 201 als minstens één slaagt; 422 als geen enkele slaagt. Bekijk beide arrays. |

| /studio-api/scheduled-posts/update | id, expected_version, patch; optioneel overeenkomende provider_payload. | post. Een verouderde versie wordt geweigerd; de bestemming is onveranderlijk. |

| /studio-api/scheduled-posts/publish-now | id en expected_version. | post. Vraagt onmiddellijke uitvoering aan; bewijst geen publicatie. |

| /studio-api/scheduled-posts/retry | id, expected_version; optioneel toekomstige scheduled_at. | post. Herstel alleen bij mislukking en op basis van bewijs; verstuur nooit blind opnieuw. |

| /studio-api/scheduled-posts/cancel | id en expected_version. | post. Annuleert ongepubliceerd werk; annulering bij de provider kan nog in behandeling zijn. |

| /studio-api/scheduled-posts/delete | id en expected_version. | post. Machineaanroepers kunnen reeds gepubliceerde providerinhoud niet verwijderen. |

| /studio-api/scheduled-posts/withdraw-delete | id en expected_version. | post. Trekt een gestopt, alleen ter verificatie bedoeld Instagram Login-verwijderingsverzoek in; behoudt providerinhoud. |

## 3. Geef lijsten en pagina's weer binnen hetzelfde bereik

limit is standaard 50 en accepteert 1–200. Optionele status is scheduled, publishing, published, failed, expired, needs_reschedule, cancelled of deleted. scheduled_from en scheduled_to moeten samen worden opgegeven als ISO-8601-tijdstippen met tijdzone-offsets; het einde moet na het begin liggen.

next_cursor is null of een object met scheduled_at en id. Stuur dat volledige object terug als cursor met dezelfde werkruimte en filters. Dit endpoint accepteert geen filters page, offset, platform of social_account_id.

```
await sosoPost("/studio-api/scheduled-posts/list", {
  "workspace_id": "<workspace-uuid>",
  "limit": 50
});
```

```
const first = await sosoPost("/studio-api/scheduled-posts/list", {
  workspace_id: "<workspace-uuid>", limit: 50
});
if (first.next_cursor) {
  const next = await sosoPost("/studio-api/scheduled-posts/list", {
    workspace_id: "<workspace-uuid>", limit: 50, cursor: first.next_cursor
  });
  // Consume next.posts; continue only while next_cursor is not null.
}
```

## 4. Valideer en maak één beoordeeld bericht

Vervang elke placeholder door waarden uit je toegestane bereik en een toekomstig tijdstip. Dit voorbeeld plant bij uitvoering een echt Threads-tekstbericht in. Laat de persoon het account, de inhoud en het tijdstip bevestigen vóór de aanmaakaanroep.

Stel provider_payload.platform en de publish_options van dat platform in. De server controleert of ze bij het geselecteerde account passen. Je kunt project_id toevoegen om de herkomst vast te leggen; het project verleent geen publicatietoegang en beheert de planning niet.

Velden en standaardwaarden van het aanmaakverzoek

| Veld | Contract |

| --- | --- |

| workspace_id / social_account_id | Verplichte UUIDs voor de toegestane werkruimte en exacte bestemming. |

| provider_payload | Verplichte platformdiscriminator en platformspecifieke publish_options. |

| scheduled_at / display_timezone | Verplicht ISO-8601-tijdstip met offset; geldige IANA-weergavetijdzone, standaard UTC. |

| idempotency_key | Verplichte tekenreeks zonder omringende witruimte, 8–160 tekens, stabiel voor deze ene intentie. |

| caption / hashtags | Caption mag null zijn, maximaal 5,000 tekens; standaard null. Hashtags is standaard []; maximaal 100 tekenreeksen van 100 tekens. Providerlimieten kunnen strenger zijn. |

| media | Standaard []; maximaal 20 geregistreerde mediaverwijzingen. Elk heeft kind image/video en een canonieke url; voeg de gereedstaande asset_id toe. Platformregels kunnen strenger zijn. |

| link_url | Optionele URL of null. De bestemming en het berichttype moeten dit ondersteunen. |

| local_scheduled_at / schedule_dst_disambiguation | Optioneel paar: lokale tijd zonder offset en exact/earlier/later. Geef beide of geen van beide mee; ze moeten overeenkomen met het bedoelde tijdstip en de tijdzone. |

| expires_at / automatic_retry_enabled | Optionele vervaldatum na scheduled_at; null betekent geen vervaldatum. Automatisch opnieuw proberen is standaard true en blijft onderworpen aan providerveiligheid. |

| project_id / source_ref | Optionele nullable Project-UUID en herkomstobject van de aanroeper. Geen van beide wijzigt bevoegdheden. |

```
await sosoPost("/studio-api/scheduled-posts/eligibility", {
  "workspace_id": "<workspace-uuid>",
  "include_quota": true,
  "targets": [
    {
      "social_account_id": "<threads-account-uuid>",
      "media": [],
      "provider_payload": {
        "platform": "threads",
        "publish_options": {
          "post_type": "TEXT"
        }
      },
      "draft": {
        "caption": "A reviewed update from our team.",
        "hashtags": [],
        "scheduled_at": "<future-ISO-8601-instant-with-offset>",
        "display_timezone": "Asia/Hong_Kong"
      }
    }
  ]
});
```

```
await sosoPost("/studio-api/scheduled-posts/create", {
  "workspace_id": "<workspace-uuid>",
  "social_account_id": "<threads-account-uuid>",
  "caption": "A reviewed update from our team.",
  "hashtags": [],
  "media": [],
  "provider_payload": {
    "platform": "threads",
    "publish_options": {
      "post_type": "TEXT"
    }
  },
  "scheduled_at": "<future-ISO-8601-instant-with-offset>",
  "display_timezone": "Asia/Hong_Kong",
  "idempotency_key": "<stable-key-for-this-one-intent>"
});
```

## 5. Lees het resultaat en annuleer veilig

Aanmaken geeft { post, deduped } terug. Lijst geeft { posts, next_cursor, returned_count } terug. Ophalen geeft { post, delivery, actions, attempts, outcomes } terug. Een post bevat id, status, version, destination, schedule en beschikbare provideridentiteit/permalink; delivery en actions verklaren huidige voortgang en toegestane vervolgstappen.

Een bericht met status scheduled of publishing is nog in behandeling. Een definitief publicatieresultaat met status published bevestigt publicatie en bevat het beschikbare providerbewijs; een permalink kan ontbreken. Lees bij verbroken clientverbinding of vertraagd antwoord het bestaande bericht voordat je een resultaat meldt.

Haal vóór annulering het berichtdetail op en geef de huidige numerieke versie mee. Het resultaat kan cancellation_pending zijn terwijl SosoAPI een bij de provider beheerde planning annuleert. Een planning annuleren verwijdert geen reeds gepubliceerd bericht.

```
await sosoPost("/studio-api/scheduled-posts/get", {
  "id": "<scheduled-post-uuid>"
});
```

```
const detail = await sosoPost("/studio-api/scheduled-posts/get", {
  id: "<scheduled-post-uuid>"
});
// Run only after the person confirms cancelling this unpublished post.
await sosoPost("/studio-api/scheduled-posts/cancel", {
  id: detail.post.id, expected_version: detail.post.version
});
```

## 6. Idempotentie, conflicten en onzekere schrijfhandelingen

Gebruik dezelfde idempotency_key wanneer je hetzelfde aanmaakverzoek herhaalt. Een overeenkomende herhaling geeft het bestaande bericht terug met deduped=true. Gewijzigde inhoud met dezelfde sleutel veroorzaakt een conflict. Dit voorkomt dubbele aanmaak in SosoAPI; het garandeert geen precies eenmalige aflevering door de provider.

Geef voor updates en acties expected_version uit het laatste detailantwoord mee. Haal bij een conflict het bericht opnieuw op en beoordeel je wijziging tegenover de nieuwe versie. Een verloren antwoord is reden om de bestaande status te controleren, niet om een nieuw bericht met een nieuwe sleutel te maken.

De controle op dubbele inhoud kan een apart verzoek weigeren met dezelfde genormaliseerde openbare inhoud, hetzelfde account en een nabijgelegen publicatietijd. Bekijk de verwijzing naar het bestaande bericht als je die mag lezen en vraag de gebruiker voordat je het verzoek wijzigt. Bulkverzoeken geven een resultaat per bestemming; sommige kunnen slagen terwijl andere mislukken.

## 7. Fouten, aanvraaglimieten en integratiebeperkingen

Handlerfouten gebruiken een structuur met error, message, optionele code, retryable, request_id, optionele details en retry_after_seconds. Een 400 bij schemavalidatie heeft een andere vorm: { success: false, error: { name: "ZodError", message: "…" } }. De validatiemelding bevat momenteel de geserialiseerde veldproblemen, inclusief paden; neem niet aan dat de handlervelden aanwezig zijn.

Bewaar bij foutdiagnose HTTP-status, foutcode en correlatie-ID uit result.request_id ?? response.headers.get("x-request-id"). Gebruik validatieveldpaden om het verzoek te corrigeren. Herstel bij authenticatie- of machtigingsfouten eerst de inloggegevens of machtiging voordat je opnieuw probeert.

De huidige studio-api-limiet is 240 verzoeken per minuut per menselijke gebruiker en 480 per minuut in de aparte categorie voor machine-inloggegevens van die gebruiker. Dit zijn aanvraagplafonds, geen publicatiedoorvoer of abonnementsquota. Andere endpoints en socialmediaproviders hebben aparte limieten. Volg de actuele Retry-After-header bij 429 of opnieuw probeerbare 503; gebruik geen voortdurende lus.

Lees de status met begrensde tussenpozen terwijl de gebruiker het bericht volgt, of gebruik de live statusweergave van de app. Deze API belooft geen uitgaande webhooks, abonnee-SLA, identieke platformfuncties of vaste publicatietijd.

HTTP-antwoorden en nuttige vervolgstappen

| Status | Betekenis en reactie |

| --- | --- |

| 400 | Schemavalidatie kan success:false met een ZodError in error teruggeven in plaats van de handlerstructuur. Corrigeer de veldproblemen; gebruik x-request-id als de inhoud geen request_id bevat. Ongeldige of niet-ondersteunde verzoeken op handlerniveau kunnen ook 400 gebruiken. |

| 401 / 403 | Ontbrekende/verlopen inloggegevens of geweigerde bevoegdheid, rol, werkruimte- of accounttoegang. Herstel de betreffende machtiging of het lidmaatschap. |

| 404 | De resource is niet beschikbaar binnen het toegestane bereik. Verifieer de identiteit. |

| 409 | Conflict in status/versie, idempotentie, dubbele inhoud of geschiktheid. Lees opnieuw; verstuur niet blind opnieuw. |

| 422 bij bulk-create | Geen bestemming geslaagd. Bekijk failures; gedeeltelijk succes gebruikt 201. |

| 429 | Aanvraagbegrenzing. Volg Retry-After en behoud dezelfde intentie-identiteit. |

| 503 / overige 5xx | Tijdelijke servicefout of interne fout. Bewaar request_id; bekijk bestaande status voordat je een onzekere wijziging opnieuw probeert. |

- [Matrix van platformmogelijkheden](https://sosoapi.ai/nl/docs/publishing-capabilities)

- [Configureer je eigen AI-agent](https://sosoapi.ai/nl/docs/quickstart)
