Skip to Content
IntegrationsContent Creation API

Content Creation API (application token)

This API lets an external system create content in a Syntphony community without a signed-in user. It is the right choice for scheduled jobs, external CMS tools, migration or synchronization tools, and any backend-to-backend integration.

PropertyValue
Base URLhttps://<your-tenant>.togo-provisioning-api.azurewebsites.net
EndpointPOST app/provisioning/content/add
AuthenticationOAuth 2.0 Client Credentials (application token)
Content-Typeapplication/json
Maximum request sizeAbout 30 MB

To only read public content, use the read-only public API instead. This page covers creating content with an application identity.

Prerequisites

Ask your Syntphony administrator for:

  1. An Entra ID app registration for your integration (client_id and client_secret).
  2. The Tenant ID of the Syntphony Microsoft 365 tenant.
  3. Confirmation that your application has been granted the access_as_application app role on the Syntphony Backend API app registration, with admin consent. Without it, every call returns 403 Forbidden.
  4. The community identifiers you can publish into: siteRelativeUrl (for example /sites/Contoso) and, optionally, the community key (GUID).
  5. The addonId (GUID) of each content type you want to create (Announcements, Applications, News/Pages). These values are specific to each tenant.
  6. The GUIDs of any category, tag, department or location used by your content. They must already exist in the target site; the API does not create them.

Step 1: Get an application token

Request a token directly from Microsoft Entra ID with the client credentials grant.

POST https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token Content-Type: application/x-www-form-urlencoded grant_type=client_credentials &client_id={client_id} &client_secret={client_secret} &scope={scope}
  • {scope} has the form api://<Backend-API-app-id>/.default. Ask your administrator for the exact value.
{ "token_type": "Bearer", "expires_in": 3599, "ext_expires_in": 3599, "access_token": "eyJ0eXAiOiJKV1Qi..." }

Use access_token as a Bearer token on every call. Tokens last about one hour: cache the token and refresh it before it expires instead of requesting a new one per call.

$tenantId = "<TENANT_ID>" $clientId = "<CLIENT_ID>" $clientSecret = "<CLIENT_SECRET>" $scope = "api://<Backend-API-app-id>/.default" $tokenBody = @{ grant_type = "client_credentials" client_id = $clientId client_secret = $clientSecret scope = $scope } $tokenResponse = Invoke-RestMethod -Method Post ` -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" ` -ContentType "application/x-www-form-urlencoded" ` -Body $tokenBody $accessToken = $tokenResponse.access_token

Step 2: Create the content

POST {baseUrl}/app/provisioning/content/add Authorization: Bearer {access_token} Content-Type: application/json Sessionid: <optional-correlation-id>
HeaderRequiredNotes
AuthorizationYesBearer <access_token> from Step 1.
Content-TypeYesapplication/json.
SessionidNoFree-form value used only to trace a request.

Response

200 OK with the created item:

{ "uniqueId": "3f2c9b1a-1234-4a1b-9abc-1122334455aa", "webRelativeUrl": "/sites/Contoso/Lists/Announcements/DispForm.aspx?ID=42" }

Errors use a standard envelope:

{ "message": "Human readable message", "code": "SOME_ERROR_CODE", "additionalData": null }
StatusMeaning
400Invalid payload or missing required field.
401Missing, expired or invalid token.
403Valid token, but the application does not have the access_as_application role.
404Community or content type not found.
500Unexpected error. Retry with backoff.

Request body

MemberTypeRequiredDescription
communityobjectYesTarget community.
fieldsobjectYesFields of the content item (title, summary, taxonomy, and so on).
addonIdstring (GUID)YesIdentifier of the content type configured in your tenant.

community

{ "community": { "text": "Contoso", "key": "<community-guid>", "siteRelativeUrl": "/sites/Contoso" } }
  • siteRelativeUrl is the recommended way to target a community. If present, it is used directly.
  • If it is omitted, the community is resolved by key. Provide at least one of the two.
  • text is informational only.

Common fields

FieldTypeNotes
titlestringRequired for all content types.
summary / descriptionstringDepends on the content type.
authorobjectaccount, loginName, email, name, entityType. Use a real user or service account of the tenant.
categoryobject { key, text }Must be an existing term.
tagsarray of { key, text }Must be existing terms.
departmentsarray of { key, text }Must be existing terms.
locationsarray of { key, text }Must be existing terms.
relativeListUrl / relativeFolderPathstringTarget list or folder. It must already exist.
togoApplyAudience / togoAudienceTypebool / stringAudience targeting. "custom" is the usual value.

Examples by content type

Replace every GUID and URL with the real values of your tenant. The examples target a community called Contoso at /sites/Contoso.

Announcement

{ "community": { "text": "Contoso", "siteRelativeUrl": "/sites/Contoso" }, "fields": { "title": "Quarterly results are in", "summary": "Read the highlights of this quarter's results.", "image": { "url": "https://<tenant>.sharepoint.com/sites/Contoso/SiteAssets/announcement.png" }, "author": { "account": "i:0#.f|membership|svc-content@<tenant>.onmicrosoft.com", "loginName": "i:0#.f|membership|svc-content@<tenant>.onmicrosoft.com", "email": "svc-content@<tenant>.onmicrosoft.com", "name": "Content Service Account", "entityType": "User" }, "category": { "key": "<category-guid>", "text": "Default" }, "tags": [ { "key": "<tag-guid>", "text": "results" } ], "relativeListUrl": "/sites/Contoso/Lists/Announcements", "relativeFolderPath": "/", "departments": [ { "key": "<department-guid>", "text": "Finance" } ], "locations": [ { "key": "<location-guid>", "text": "Barcelona" } ], "togoApplyAudience": true, "togoAudienceType": "custom" }, "addonId": "<announcements-addon-guid>" }

Application

{ "community": { "text": "Contoso", "siteRelativeUrl": "/sites/Contoso" }, "fields": { "title": "Expense Tool", "description": "Submit and track your expense reports.", "image": { "url": "https://<tenant>.sharepoint.com/sites/Contoso/SiteAssets/expense-tool.jpg" }, "category": { "key": "<category-guid>", "text": "Finance Tools" }, "author": { "account": "i:0#.f|membership|svc-content@<tenant>.onmicrosoft.com", "loginName": "i:0#.f|membership|svc-content@<tenant>.onmicrosoft.com", "email": "svc-content@<tenant>.onmicrosoft.com", "name": "Content Service Account", "entityType": "User" }, "tags": [ { "key": "<tag-guid>", "text": "finance" } ], "togoApplicationUrl": "https://expenses.example.com", "togoHighlight": true, "relativeListUrl": "/sites/Contoso/Lists/Applications", "togoSummaryDetails": "Submit and track your expense reports.", "togoImagesDetails": [ { "url": "https://<tenant>.sharepoint.com/sites/Contoso/SiteAssets/expense-tool-detail.jpg" } ] }, "addonId": "<applications-addon-guid>" }

News / Page

{ "community": { "text": "Contoso", "siteRelativeUrl": "/sites/Contoso" }, "fields": { "title": "New office opening in Madrid", "summary": "We are excited to announce our new office location.", "category": { "key": "<category-guid>", "text": "Corporate" }, "author": { "account": "i:0#.f|membership|svc-content@<tenant>.onmicrosoft.com", "loginName": "i:0#.f|membership|svc-content@<tenant>.onmicrosoft.com", "email": "svc-content@<tenant>.onmicrosoft.com", "name": "Content Service Account", "entityType": "User" }, "publishingDate": "2026-01-15T00:00:00.000Z", "dueDate": "2026-06-30T00:00:00.000Z", "tags": [ { "key": "<tag-guid>", "text": "corporate" } ], "relativeFolderPath": "/", "departments": [ { "key": "<department-guid>", "text": "Corporate" } ], "locations": [ { "key": "<location-guid>", "text": "Madrid" } ], "togoApplyAudience": true, "togoAudienceType": "custom" }, "addonId": "<news-addon-guid>" }

News and pages are also scheduled automatically from publishingDate and dueDate. No extra action is needed.

Full example: token and content

$tenantId = "<TENANT_ID>" $clientId = "<CLIENT_ID>" $clientSecret = "<CLIENT_SECRET>" $scope = "api://<Backend-API-app-id>/.default" $baseUrl = "https://<your-tenant>.togo-provisioning-api.azurewebsites.net" $tokenResponse = Invoke-RestMethod -Method Post ` -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" ` -ContentType "application/x-www-form-urlencoded" ` -Body @{ grant_type = "client_credentials" client_id = $clientId client_secret = $clientSecret scope = $scope } $headers = @{ Authorization = "Bearer $($tokenResponse.access_token)" Sessionid = [guid]::NewGuid().ToString() } $body = Get-Content -Raw -Path ".\announcement.json" $result = Invoke-RestMethod -Method Post ` -Uri "$baseUrl/app/provisioning/content/add" ` -Headers $headers ` -ContentType "application/json" ` -Body $body $result

Best practices

  • Store the client secret in a secure vault, never in source code.
  • Cache the token and refresh it shortly before it expires.
  • Send one content item per request.
  • Retry 500 errors with exponential backoff.
  • Request only the access_as_application role, on an app registration dedicated to this integration.

Troubleshooting

SymptomLikely causeAction
401 UnauthorizedMissing, expired or invalid token.Request a new token and check client_id, client_secret, tenant_id and scope.
403 ForbiddenThe application does not have the access_as_application role.Ask your administrator to grant the role and give admin consent.
404 for the communitysiteRelativeUrl or key does not match an existing community.Check the community identifier with your administrator.
400 on fieldsA taxonomy term, list or folder does not exist in the target site.Check the GUIDs and paths in the SharePoint site.
Content created but not visibleAudience fields restrict who can see it.Review the audience configuration with your administrator.