Last updated: August 28, 2026
This document is intended for developers, QA engineers, implementation teams, and automation engineers integrating with the SocialEcho external API.
It covers teams, accounts, authorization links, posts, reports, OSS uploads, Reddit communities, Pinterest boards, TikTok Shop products and music, and cross-platform publishing through a Team API Key. Brand, AI generation, and document-management APIs are outside the scope of this version.
Authorization: Bearer se_xxx.GET /v1/team first to verify authentication and the team context.code for the specific business result.| Field | Value |
|---|---|
| Base URL | https://api.socialecho.net |
| Authentication | Bearer Token (Team API Key) |
| Required header | Authorization: Bearer se_your_team_api_key |
| Optional language header | X-Lang: zh_CN or en |
| Rate limit | Maximum 120 requests per minute per API key |
Place all business parameters for GET endpoints in the query string. Do not send a request body with a GET request. Use bracketed keys for arrays, for example account_ids[]=1&account_ids[]=2.
CloudFront may return an HTML 403 Bad request response when a GET request contains a body.
200-299 and JSON code = 0. All successful endpoints documented here currently return HTTP 200.400-599 and a non-zero business code. Business failures are not returned as HTTP 200.code, error.type, and data for detailed handling.2xx responses, still attempt to parse the JSON body and record request_id.Success:
{
"code": 0,
"message": "Success",
"data": {},
"request_id": "018f7f35-7c9a-7b82-a0f2-6a06b0b7d301"
}
Failure:
{
"code": 42200,
"message": "Request validation failed",
"data": {
"account_id": ["Please select a TikTok Shop account"]
},
"error": {
"type": "invalid_request",
"reason": "Request validation failed",
"suggestion": "Check the request parameters and try again"
},
"request_id": "018f7f35-7c9a-7b82-a0f2-6a06b0b7d301"
}
The server also returns X-Request-Id in the response headers. A caller may provide a correctly formatted X-Request-Id, or use the server-generated value for request tracing. Paginated success responses also include meta.
| HTTP status | Standard code | Meaning and recommended action |
|---|---|---|
| 400 Bad Request | 40000 |
Invalid request syntax, format, or basic parameters. Correct the request before retrying. |
| 401 Unauthorized | 40100 |
Missing, invalid, or expired API key. Check Authorization: Bearer .... |
| 403 Forbidden | 40300 |
Authenticated but not permitted, such as missing draft permission. Do not retry unchanged. |
| 404 Not Found | 40400 |
The account, product, authorization, or another resource does not exist, is unavailable, or does not belong to the team. |
| 405 Method Not Allowed | 40500 |
Unsupported HTTP method. Use the method shown in the Allow response header. |
| 409 Conflict | 40900 |
The resource state conflicts with the operation. Refresh the resource state before retrying. |
| 413 Payload Too Large | 41300 |
Request body or upload exceeds a server limit. Reduce its size. |
| 419 Authentication Timeout | 41900 |
Session or security token expired. This should not normally occur for Team API Key endpoints. |
| 422 Unprocessable Entity | 42200 |
Field validation, publishing rules, or a recoverable business prerequisite failed. Read field errors in data. |
| 429 Too Many Requests | 42900 |
Rate limit or product-sync cooldown. Prefer Retry-After; otherwise use data.next_allowed_at or the response message. |
| 500 Internal Server Error | 50000 |
Unexpected SocialEcho error. Preserve request_id and contact support. |
| 502 Bad Gateway | 50200 |
Upstream social-platform request failed. Retry later and preserve request_id. |
| 503/504 | 50300 / 50400 |
Service unavailable or upstream timeout. Retry with backoff. |
| Timeout/network error | No response body | Retry two or three times and retain a snapshot of the request parameters. |
Standard business codes use HTTP status x 100. A small number of legacy cases may return a more specific non-zero code; this does not change the HTTP status semantics.
Automatically retry only 429, 502, 503, 504, and network timeouts. Requests returning 400, 401, 403, 404, 405, 409, 413, or 422 usually require a correction to parameters, permissions, or resource state.
All examples use https://api.socialecho.net. Replace se_your_team_api_key with your Team API Key.
GET examples intentionally omit Content-Type and a request body. Add parameters directly to the query string.
GET /v1/team)Call this endpoint first to verify the team context.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
| X-Lang | header | No | string | zh_CN or en; default: zh_CN |
curl --request GET 'https://api.socialecho.net/v1/team' \
--header 'Authorization: Bearer se_your_team_api_key' \
--header 'Accept: application/json' \
--header 'X-Lang: en'
{
"code": 0,
"message": "Success",
"data": {
"id": 1024,
"code": "TEAM_ABC123",
"title": "SocialEcho QA Team",
"thumb": "https://oss.socialecho.net/team/TEAM_ABC123/avatar.jpg",
"describe": "SocialEcho API integration team",
"created_at": "2026-08-01 02:30:00 UTC",
"timezone": {
"id": 45,
"name": "Asia/Shanghai",
"offset": "UTC+08:00",
"city": "Shanghai"
}
},
"request_id": "018f7f35-7c9a-7b82-a0f2-6a06b0b7d301"
}
GET /v1/account)| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
| X-Lang | header | No | string | Response language |
| page | query | No | integer | Page number; the server default applies when omitted |
| type | query | No | integer | 1 = authorized account; 2 = competitor account |
curl --request GET 'https://api.socialecho.net/v1/account?page=1&type=1' \
--header 'Authorization: Bearer se_your_team_api_key' \
--header 'Accept: application/json' \
--header 'X-Lang: en'
{
"code": 0,
"message": "Success",
"data": [{
"id": 163751,
"title": "example_account",
"account": "example_account",
"url": "https://www.tiktok.com/@example_account",
"app": {"id": 11, "title": "TikTokShop"},
"type": {"value": 1, "label": "Authorized account"},
"status": {"value": 1, "label": "Active"}
}],
"meta": {"total": 1, "current_page": 1, "last_page": 1, "per_page": 15},
"request_id": "018f7f35-7c9a-7b82-a0f2-6a06b0b7d301"
}
GET /v1/oauth/links)Returns one or more authorization methods for each platform available to the current team. Select a URL by using data[].id, data[].title, and connections[].type. This endpoint has no business parameters.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
| Authorization | header | Yes | string | Bearer se_your_team_api_key |
| X-Lang | header | No | string | zh_CN or en; default: zh_CN |
curl --request GET 'https://api.socialecho.net/v1/oauth/links' \
--header 'Authorization: Bearer se_your_team_api_key' \
--header 'Accept: application/json' \
--header 'X-Lang: en'
Example response, with URLs redacted:
{
"code": 0,
"message": "Success",
"data": [
{
"id": 1,
"title": "Instagram",
"connections": [
{"type": "instagram", "url": "https://authorization.example/instagram"},
{"type": "facebook", "url": "https://authorization.example/facebook"}
]
},
{
"id": 3,
"title": "TikTok",
"connections": [
{"type": "personal", "url": "https://authorization.example/tiktok"}
]
},
{
"id": 11,
"title": "TikTokShop",
"connections": [
{"type": "seller", "url": "https://authorization.example/tiktokshop/seller"},
{"type": "creator", "url": "https://authorization.example/tiktokshop/creator"}
]
}
],
"request_id": "018f7f35-7c9a-7b82-a0f2-6a06b0b7d301"
}
| Field | Type | Description |
|---|---|---|
| data[].id | integer | Platform ID; corresponds to app.id in the account list |
| data[].title | string | Platform name |
| data[].connections | object[] | Supported authorization entries |
| data[].connections[].type | string | Authorization mode for the platform |
| data[].connections[].url | string | URL to open directly; may contain team context or one-time state parameters |
| Platform | Platform ID | Connection type |
|---|---|---|
| 1 | instagram, facebook |
|
| 2 | default |
|
| TikTok | 3 | personal |
| 4 | default |
|
| YouTube | 5 | default |
| Telegram | 6 | default |
| X | 7 | default |
| 8 | personal |
|
| 9 | default |
|
| Threads | 10 | personal |
| TikTokShop | 11 | seller, creator |
Open authorization URLs exactly as returned. Do not rewrite them or remove query parameters. They may contain team-related state and should not be cached long term, publicly shared, or written to ordinary business logs. Request a new URL when authorization is needed.
| HTTP status | Code | Scenario |
|---|---|---|
| 200 | 0 |
Authorization links returned successfully |
| 401 | 40100 |
Team API Key is missing, invalid, or expired |
| 405 | 40500 |
Incorrect method; use GET |
| 422 | 42200 |
Business prerequisite failed, such as insufficient team credits |
| 500 | 50000 |
Unexpected server error while generating links |
GET /v1/article)| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
| X-Lang | header | No | string | Response language |
| page | query | No | integer | Page number |
| account_ids | query | No | integer[] | Repeat account_ids[] for each account ID |
curl --request GET 'https://api.socialecho.net/v1/article?page=1&account_ids[]=163956&account_ids[]=163955&account_ids[]=28' \
--header 'Authorization: Bearer se_your_team_api_key' \
--header 'Accept: application/json' \
--header 'X-Lang: en'
{
"code": 0,
"message": "Success",
"data": [{
"id": 987654,
"uuid": "platform_post_id",
"title": null,
"content": "Example article content",
"url": "https://www.example.com/post/platform_post_id",
"app": {"id": 3, "title": "TikTok"},
"created_at": "2026-08-27 13:00:00 +08:00",
"updated_at": "2026-08-27 13:05:00 +08:00",
"account": {
"id": 163751,
"avatar": "https://oss.socialecho.net/account/avatar.jpg",
"account": "example_account",
"title": "Example Account",
"url": "https://www.tiktok.com/@example_account"
},
"report": {
"exposure": 1021,
"like": 40,
"comment": 14,
"share": 0,
"quote": 0,
"favorite": 12
},
"attachments": [{
"id": 456789,
"url": "https://oss.socialecho.net/team/TEAM_ABC123/20260827/example.mp4",
"thumb": null,
"type": "video",
"iframe": null
}],
"quote": null
}],
"meta": {"total": 1, "current_page": 1, "last_page": 1, "per_page": 15},
"request_id": "018f7f35-7c9a-7b82-a0f2-6a06b0b7d301"
}
GET /v1/report)| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
| X-Lang | header | No | string | Response language |
| start_date | query | Yes | string | YYYY-MM-DD; must be earlier than end_date, and the range must not exceed the team's report allowance |
| end_date | query | Yes | string | YYYY-MM-DD; must not be later than today |
| time_type | query | Yes | integer | 1 = posts created in the date range; 2 = all historical posts |
| account_ids | query | No | integer[] | Repeat account_ids[] for each account ID |
| group | query | No | string | Omit for totals; day, app, or account for grouped results |
curl --request GET 'https://api.socialecho.net/v1/report?start_date=2026-01-01&end_date=2026-03-24&time_type=1&account_ids[]=163956&account_ids[]=163955&account_ids[]=28' \
--header 'Authorization: Bearer se_your_team_api_key' \
--header 'Accept: application/json' \
--header 'X-Lang: en'
The group value changes the structure of data. Parse the response according to the requested grouping.
Summary response when group is omitted:
{
"code": 0,
"message": "Success",
"data": {
"total": {
"fans": 5320,
"content": 84,
"exposure": 120345,
"comment": 893,
"like": 4512,
"share": 326,
"quote": 12,
"favorite": 645
},
"increase": {
"fans": 102,
"content": 14,
"exposure": 18340,
"comment": 116,
"like": 507,
"share": 38,
"quote": 3,
"favorite": 72
}
},
"request_id": "018f7f35-7c9a-7b82-a0f2-6a06b0b7d301"
}
Abbreviated response for group=day:
{
"code": 0,
"message": "Success",
"data": [{
"date": "2026-03-23",
"total": {"fans": 5310, "content": 6, "exposure": 8421, "comment": 52, "like": 301, "share": 19, "quote": 1, "favorite": 34},
"increase": {"fans": 12, "content": 6, "exposure": 8421, "comment": 52, "like": 301, "share": 19, "quote": 1, "favorite": 34}
}],
"request_id": "018f7f35-7c9a-7b82-a0f2-6a06b0b7d301"
}
With group=app, each data[] item contains platform id, title, total, and increase. With group=account, each item contains account id, title, account, avatar, url, app, total, and increase. Only day, app, and account are supported grouping values.
GET /v1/upload/url)The normal flow is: obtain a presigned upload URL, upload the file using the returned method, then use public_url in publishing attachments.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
| X-Lang | header | No | string | Response language |
| content_type | query | Yes | string | MIME type of the file; must match the actual file |
| title | query | No | string | File name; maximum 255 characters |
Supported content_type values:
image/jpeg, image/jpg, image/png, image/gif, image/webp, image/bmp.video/mp4, video/avi, video/mov, video/wmv, video/flv, video/webm, video/mkv, video/3gp, video/quicktime.audio/mpeg, audio/mp3, audio/wav, audio/x-wav, audio/aac, audio/mp4, audio/m4a, audio/ogg, audio/webm, audio/flac.curl --request GET 'https://api.socialecho.net/v1/upload/url?content_type=video%2Fmp4&title=product-video.mp4' \
--header 'Authorization: Bearer se_your_team_api_key' \
--header 'Accept: application/json' \
--header 'X-Lang: en'
{
"code": 0,
"message": "Success",
"data": {
"upload_url": "https://oss.socialecho.net/team/TEAM_ABC123/20260828/AbCdEf1234567890AbCdEf1234567890.mp4?signature=example",
"method": "PUT",
"public_url": "https://oss.socialecho.net/team/TEAM_ABC123/20260828/AbCdEf1234567890AbCdEf1234567890.mp4",
"object_key": "team/TEAM_ABC123/20260828/AbCdEf1234567890AbCdEf1234567890.mp4",
"headers": {"Content-Type": "video/mp4"},
"expire_in": 600,
"file_id": 123456,
"file": {
"id": 123456,
"url": "https://oss.socialecho.net/team/TEAM_ABC123/20260828/AbCdEf1234567890AbCdEf1234567890.mp4",
"title": "product-video.mp4",
"extension": "mp4",
"mime": "video/mp4",
"type": "video",
"size": 0,
"status": "pending",
"extra": [],
"created_at": "2026-08-28 10:00:00 +08:00",
"updated_at": "2026-08-28 10:00:00 +08:00"
}
},
"request_id": "018f7f35-7c9a-7b82-a0f2-6a06b0b7d301"
}
Use the returned method, upload_url, and headers exactly as provided. The signed upload_url expires and must not be modified, cached, or used for publishing.
curl --request PUT 'upload_url_from_previous_response' \
--header 'Content-Type: video/mp4' \
--upload-file './product-video.mp4'
After upload, use public_url in the publishing request. Audio upload support does not imply that every publishing platform and type accepts audio attachments.
Success returns HTTP 200 and code = 0. Missing, invalid, or overlong parameters return HTTP 422 and code = 42200. An unexpected error while generating the upload URL returns HTTP 500 and code = 50000. Submit only a MIME type listed above; unsupported MIME types currently return HTTP 500 and code = 50000.
GET /v1/reddit/communities)Use this endpoint to select a community before publishing to Reddit.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
| X-Lang | header | No | string | Response language |
| account_id | query | Yes | integer | Reddit social account ID |
curl --request GET 'https://api.socialecho.net/v1/reddit/communities?account_id=163751' \
--header 'Authorization: Bearer se_your_team_api_key' \
--header 'Accept: application/json' \
--header 'X-Lang: en'
{
"code": 0,
"message": "Success",
"data": [{
"id": 301,
"uuid": "t5_example",
"title": "example-community",
"attributes": {
"description": "Example community",
"avatar": "https://styles.redditmedia.com/example.png",
"subscribers": 12000,
"permissions": {
"release": true,
"type": ["text", "media", "link"]
}
},
"created_at": "2026-08-28 10:00:00",
"updated_at": "2026-08-28 10:00:00"
}],
"meta": {"total": 1, "current_page": 1, "last_page": 1, "per_page": 15},
"request_id": "018f7f35-7c9a-7b82-a0f2-6a06b0b7d301"
}
When publishing to Reddit, use the integer data[].id as extra.category_id, not uuid. Verify attributes.permissions.release = true and that the target post type appears in attributes.permissions.type. The community list does not guarantee flair options. Omit extra.flair when no valid flair has been confirmed; do not submit an empty object.
GET /v1/pinterest/boards)Use this endpoint to select a board before publishing to Pinterest.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
| X-Lang | header | No | string | Response language |
| account_id | query | Yes | integer | Pinterest social account ID |
curl --request GET 'https://api.socialecho.net/v1/pinterest/boards?account_id=163751' \
--header 'Authorization: Bearer se_your_team_api_key' \
--header 'Accept: application/json' \
--header 'X-Lang: en'
{
"code": 0,
"message": "Success",
"data": [{
"id": 401,
"uuid": "987654321012345678",
"title": "Home Decor",
"attributes": {},
"created_at": "2026-08-28 10:00:00",
"updated_at": "2026-08-28 10:00:00"
}],
"meta": {"total": 1, "current_page": 1, "last_page": 1, "per_page": 15},
"request_id": "018f7f35-7c9a-7b82-a0f2-6a06b0b7d301"
}
Use the integer data[].id as extra.category_id when publishing. Do not use the platform board uuid.
GET /v1/tiktokshop/products)Returns products synchronized for a TikTok Shop account. Before publishing a shoppable video or photo post, obtain the complete id, uuid, title, and thumb from this endpoint.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
| account_id | query | Yes | integer | TikTok Shop account ID from /v1/account |
| page | query | No | integer | Page number; default: 1 |
| per_page | query | No | integer | Items per page; 1-100; default: 20 |
| keyword | query | No | string | Product-title keyword; maximum 500 characters |
curl --request GET 'https://api.socialecho.net/v1/tiktokshop/products?account_id=123456&page=1&per_page=20&keyword=vase' \
--header 'Authorization: Bearer se_your_team_api_key' \
--header 'Accept: application/json' \
--header 'X-Lang: en'
{
"code": 0,
"message": "Success",
"data": [{
"id": 789,
"uuid": "1732443576158556877",
"title": "Ceramic Flower Vase",
"thumb": "https://oss.socialecho.net/team/TEAM_ABC123/20260828/product.jpg",
"status": 1,
"price": {"min": "68.88", "max": "68.88", "currency": "USD"}
}],
"meta": {"total": 1, "current_page": 1, "last_page": 1, "per_page": 20},
"request_id": "018f7f35-7c9a-7b82-a0f2-6a06b0b7d301"
}
status = 1 means the product is currently available for publishing. If a localized keyword returns no result, try the product's English title or omit keyword to retrieve all products.
| HTTP status | Code | Scenario |
|---|---|---|
| 200 | 0 |
Product list returned successfully |
| 404 | 40400 |
TikTok Shop account does not exist, is unavailable or unauthorized, or does not belong to the team |
| 422 | 42200 |
Invalid account_id, pagination, or keyword parameter |
| 500 | 50000 |
Unexpected server error while querying products |
POST /v1/tiktokshop/products/sync)Requests an asynchronous refresh of products for the account. A successful response means the job entered the queue, not that synchronization has finished. Each account has an approximate 60-minute cooldown.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
| account_id | body | Yes | integer | TikTok Shop account ID |
curl --request POST 'https://api.socialecho.net/v1/tiktokshop/products/sync' \
--header 'Authorization: Bearer se_your_team_api_key' \
--header 'Content-Type: application/json' \
--header 'X-Lang: en' \
--data-raw '{"account_id":123456}'
{
"code": 0,
"message": "Product sync job submitted",
"data": {
"account_id": 123456,
"status": "queued"
},
"request_id": "018f7f35-7c9a-7b82-a0f2-6a06b0b7d301"
}
| HTTP status | Code | Scenario |
|---|---|---|
| 200 | 0 |
Sync job queued |
| 404 | 40400 |
Account does not exist, is unavailable or unauthorized, or does not belong to the team |
| 422 | 42200 |
Missing account_id, or account type does not support product synchronization |
| 429 | 42900 |
Sync is running or cooling down; wait according to data.next_allowed_at, Retry-After when present, or the response message |
| 500 | 50000 |
Failed to submit the sync job; preserve request_id and contact support |
GET /v1/tiktokshop/music/genres)Returns genres supported by the trending-music endpoint. This endpoint has no business parameters.
curl --request GET 'https://api.socialecho.net/v1/tiktokshop/music/genres' \
--header 'Authorization: Bearer se_your_team_api_key' \
--header 'Accept: application/json' \
--header 'X-Lang: en'
Abbreviated response:
{
"code": 0,
"message": "Success",
"data": [
{"value": "ALL", "label": "All"},
{"value": "POP", "label": "Pop"},
{"value": "BGM", "label": "Background Music"}
],
"request_id": "018f7f35-7c9a-7b82-a0f2-6a06b0b7d301"
}
Success returns HTTP 200 and code = 0. A business prerequisite such as insufficient credits returns HTTP 422 and code = 42200. Unexpected server errors return HTTP 500 and code = 50000. Authentication and method errors follow Section 4.
GET /v1/tiktokshop/music/trending)Returns available tracks from the TikTok Commercial Music Library. account_id may be an active TikTok Shop account ID or a directly authorized TikTok account ID in the current team. For a TikTok Shop account, the server resolves an associated or available TikTok authorization.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
| account_id | query | Yes | integer | TikTok Shop or authorized TikTok account ID |
| country_code | query | No | string | Two-letter country code, such as US; default: US |
| genre | query | No | string | Value returned by the genres endpoint; default: ALL |
| date_range | query | No | string | 1DAY, 7DAY, 30DAY, or 90DAY; default: 30DAY |
curl --request GET 'https://api.socialecho.net/v1/tiktokshop/music/trending?account_id=123456&country_code=US&genre=BGM&date_range=7DAY' \
--header 'Authorization: Bearer se_your_team_api_key' \
--header 'Accept: application/json' \
--header 'X-Lang: en'
{
"code": 0,
"message": "Success",
"data": [{
"uuid": "6817383821571262465",
"title": "A lovely acoustic song",
"artist": "Hiraoka",
"url": "https://example.tiktokcdn.com/music",
"cover": "https://example.tiktokcdn.com/cover.jpeg",
"duration": 81
}],
"request_id": "018f7f35-7c9a-7b82-a0f2-6a06b0b7d301"
}
| Field | Type | Description |
|---|---|---|
| uuid | string | Unique music ID; publish it as extra.music.uuid |
| title | string | Track title |
| artist | string | Artist or performer |
| url | string | Audio preview URL |
| cover | string | Cover image URL |
| duration | integer | Duration in seconds |
selection, music_volume, and original_sound_volume are publishing controls and are not returned by the music endpoint. When music is selected, copy all six returned fields (url, uuid, cover, title, artist, and duration) unchanged into extra.music, then add the three publishing controls. Do not submit only a UUID or a reduced four-field object.
Complete music object:
{
"url": "https://sf16-ies-music-sg.tiktokcdn.com/obj/tos-alisg-ve-2102/oUNQD7eSEFCC1sggYZ9DQY0OdArrcwoj6BofBk",
"uuid": "7231997808928032770",
"cover": "https://p16-sg.tiktokcdn.com/aweme/100x100/tos-alisg-v-2774/oYHMADhIgAFdBaDftgrjLQoIsFZSsCeZEIpBAa.jpeg",
"title": "Boundless Worship",
"artist": "Josué Novais Piano Worship",
"duration": 715,
"selection": "trending_clip",
"music_volume": 50,
"original_sound_volume": 0
}
| HTTP status | Code | Scenario |
|---|---|---|
| 200 | 0 |
Trending music returned successfully |
| 404 | 40400 |
TikTok Shop account does not exist, or no TikTok authorization is available for the music query |
| 422 | 42200 |
Invalid account, country, genre, or date range |
| 429 | 42900 |
Rate limit reached; retry after Retry-After |
| 502 | 50200 |
Upstream TikTok music service failed |
| 500 | 50000 |
Other unexpected server error |
POST /v1/publish/article)This endpoint publishes across platforms. type, extra, and attachments are platform-specific.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
| X-Lang | header | No | string | Response language |
| account_id | body | Yes | integer | Social account ID used for publishing |
| type | body | Yes | string | Platform-specific publishing type |
| status | body | Yes | integer | 0 = draft; 1 = publish |
| scheduled_at | body | No | string | Schedule used only when status = 1; omit for immediate publishing. Values without an offset are parsed in the team timezone. |
| comment | body | No | string or string[] | Comments. A string is normalized to an array; clients should send an array. Maximum 10 on supported platforms. |
| content | body | Conditional | string | Main post text; required for some platforms and types |
| extra | body | Conditional | object | Platform-specific fields |
| attachments | body | Conditional | object[] | Platform-specific media list. Each item must include the uploaded file url; a video cover may be supplied as thumb. |
Attachment url and thumb must be recognized by the configured SocialEcho OSS. Use the public_url returned by GET /v1/upload/url. The server resolves media type, dimensions, size, duration, and frame rate from OSS; clients do not submit that metadata.
Supported type examples:
reels, post, storiesshorts, videoreels, post, storiesshort_post, long_postpostvideo, photovideo, photoposttext, link, mediapostpostThe table lists the primary validation rules enforced by the current external publishing endpoint. File limits apply per attachment. Media dimensions, frame rate, duration, and aspect ratio are resolved and validated by the server.
| Platform / type | content |
Important extra fields |
Attachment rules |
|---|---|---|---|
Facebook reels |
Optional; max 2,200 characters | No required extension fields | Exactly 1 video; max 1 GiB; min 540x540; 23-60 fps; 3-300 seconds |
Facebook post |
At least content or media; max 2,200 characters | No required extension fields | Optional: 1-10 images/GIFs or 1 video; images and video cannot be mixed |
Facebook stories |
Content not supported | No required extension fields | Exactly 1 image or video; image max 10 MiB; video max 2 GiB |
YouTube shorts |
Required; 1-5,000 characters; max 60 hashtags | title required, max 100 characters; tags and containsSyntheticMedia optional |
Exactly 1 video; max 2 GiB; min 480x480; 1-180 seconds |
YouTube video |
Optional; max 5,000 characters; max 60 hashtags | title required, max 100 characters; tags and containsSyntheticMedia optional |
Exactly 1 video; max 2 GiB; 1-43,200 seconds |
Instagram reels |
Optional; max 2,200 characters and 30 hashtags | collaborators optional; max 3 usernames |
Exactly 1 video; max 300 MiB; 23-60 fps; 3-900 seconds; 9:16 |
Instagram post |
Optional; max 2,200 characters and 30 hashtags | collaborators optional; max 3 usernames |
1-10 images, GIFs, or videos |
Instagram stories |
Content and collaborators not supported | No required extension fields | Exactly 1 image or video; image max 10 MiB; video max 2 GiB |
X short_post |
Optional; max 280 characters | No required extension fields | Optional; max 4 images, GIFs, or videos |
X long_post |
Optional; max 25,000 characters | No required extension fields | Optional; max 4 images, GIFs, or videos |
LinkedIn post |
Optional; max 3,000 characters | No required extension fields | Optional; max 20 total; up to 20 images/GIFs and up to 1 video |
TikTok video |
Optional; max 2,200 UTF-16 code units | draft required boolean; is_ai_generated and music optional; title unsupported |
Exactly 1 video; max 1 GiB; min 360x360; 23-60 fps; 3-600 seconds |
TikTok photo |
Optional; max 4,000 UTF-16 code units | draft required boolean; title optional, max 90 UTF-16 code units; music optional |
1-35 jpg, jpeg, or webp images; max 20 MiB each |
Pinterest post |
Optional; max 500 characters | category_id required integer from board data[].id; title max 100 characters |
Exactly 1 image, GIF, or video |
Reddit text |
Required | title required, max 300 characters; category_id and flair optional |
Attachments prohibited |
Reddit link |
Optional | title and link required; category_id and flair optional |
Attachments prohibited |
Reddit media |
Optional | title required; category_id and flair optional |
1-20 total; up to 20 images/GIFs and up to 1 video |
Threads post |
Optional; max 500 characters | No required extension fields | Optional; max 20 images or videos; GIF unsupported |
Telegram post |
Optional; max 4,096 characters | No required extension fields | Optional; max 10 images or videos; comment unsupported |
YouTube extra.tags must be an array of strings with no empty values, duplicates, or control characters. The combined length under YouTube's comma-and-quote counting rules must not exceed 500. Supply a YouTube thumbnail through attachments[0].thumb; only jpg, jpeg, and png are supported, with a 2 MiB maximum.
Instagram extra.collaborators must be an array of username strings, with or without a leading @. Usernames may contain only letters, numbers, periods, and underscores, and must not be duplicated. For Reddit, omit extra.flair entirely when it is not needed. When supplied, both uuid and title are required.
curl --request POST 'https://api.socialecho.net/v1/publish/article' \
--header 'Authorization: Bearer se_your_team_api_key' \
--header 'Content-Type: application/json' \
--header 'X-Lang: en' \
--data @publish-payload.json
Complete these steps before publishing:
/v1/account and select an active TikTok Shop account ID./v1/tiktokshop/products and select the product to attach./v1/upload/url and upload the video or images to OSS.public_url returned by the upload endpoint.Video publish-payload.json example:
{
"account_id": 123456,
"type": "video",
"status": 1,
"content": "A simple statement piece for every cozy corner. #HomeDecor #TikTokShop",
"extra": {
"title": "Minimalist Ceramic Vase",
"product": {
"id": 789,
"uuid": "1732443576158556877",
"title": "Ceramic Flower Vase",
"thumb": "https://oss.socialecho.net/team/TEAM_ABC123/20260828/product.jpg"
},
"music": {
"url": "https://sf16-ies-music-sg.tiktokcdn.com/obj/tos-alisg-ve-2102/oUNQD7eSEFCC1sggYZ9DQY0OdArrcwoj6BofBk",
"uuid": "7231997808928032770",
"cover": "https://p16-sg.tiktokcdn.com/aweme/100x100/tos-alisg-v-2774/oYHMADhIgAFdBaDftgrjLQoIsFZSsCeZEIpBAa.jpeg",
"title": "Boundless Worship",
"artist": "Josué Novais Piano Worship",
"duration": 715,
"selection": "trending_clip",
"music_volume": 50,
"original_sound_volume": 0
}
},
"attachments": [{
"url": "https://oss.socialecho.net/team/TEAM_ABC123/20260828/product-video.mp4"
}],
"comment": []
}
Replace the illustrative OSS URLs with the public_url returned for the current upload. Product fields must use current values returned by the product-list endpoint.
Photo publish-payload.json example:
{
"account_id": 123456,
"type": "photo",
"status": 1,
"content": "A cozy update for your favorite corner. #HomeDecor #TikTokShop",
"extra": {
"title": "Minimalist Ceramic Vase",
"product": {
"id": 789,
"uuid": "1732443576158556877",
"title": "Ceramic Flower Vase",
"thumb": "https://oss.socialecho.net/team/TEAM_ABC123/20260828/product.jpg"
}
},
"attachments": [
{"url": "https://oss.socialecho.net/team/TEAM_ABC123/20260828/product-1.jpg"},
{"url": "https://oss.socialecho.net/team/TEAM_ABC123/20260828/product-2.jpg"}
],
"comment": []
}
TikTok Shop common requirements:
account_id must identify an active TikTok Shop account belonging to the current team.type supports only video or photo.extra.title is required, with a maximum of 30 characters. It supports Unicode letters, digits, and spaces only; punctuation is not allowed.extra.product is required. Copy id, uuid, title, and thumb directly from the product-list response.status = 1.extra.music is optional. When music is selected, include all nine fields: url, uuid, cover, title, artist, duration, selection, music_volume, and original_sound_volume.url, uuid, cover, title, artist, and duration unchanged from the current music-query result. Do not construct, truncate, or reduce the object to a UUID.extra.music.selection supports none, trending_clip, and full_track. A complete music object is required when the value is not none.music_volume and original_sound_volume must be integers from 0 to 100; the example uses 50 and 0.extra.music or send {"selection":"none"}.status = 1 without scheduled_at submits the post immediately.TikTok Shop video requirements:
content is required and must not exceed 2,200 UTF-16 code units.mp4, mov, mkv, wmv, webm, avi, 3gp, flv, mpeg, and mpg. Files of 10 MiB or more should use mp4, mov, or webm.extra.is_ai_generated is an optional boolean.TikTok Shop photo requirements:
content is optional and must not exceed 5,000 UTF-16 code units when supplied.attachments must contain at least one image and images only. The current API does not impose an image-count maximum, but TikTok Shop platform limits still apply.jpg, jpeg, png, webp, heic, and bmp. Each image must be larger than zero and no larger than 10 MiB.9:16 and 16:9.{
"code": 0,
"message": "Submitted successfully",
"data": {"id": 183308},
"request_id": "018f7f35-7c9a-7b82-a0f2-6a06b0b7d301"
}
data.id is the SocialEcho publishing-record ID. HTTP 200 with code = 0 means the job was submitted; it does not mean TikTok Shop has completed publishing. Platform processing and review are asynchronous.
| HTTP status | Code | Scenario |
|---|---|---|
| 200 | 0 |
Publishing job submitted |
| 403 | 40300 |
Team lacks draft permission when status = 0 |
| 404 | 40400 |
Team, account, or linked resource does not exist, or account does not belong to the team |
| 422 | 42200 |
Field, attachment, product, music, TikTok Shop rule, business prerequisite, or recoverable runtime validation failed |
| 500 | 50000 |
Other unexpected server error |
The asynchronous job is submitted after the publishing record is created. Therefore, an HTTP 422 or 500 during submission does not guarantee that no record was created. Do not immediately repeat the request. Preserve request_id, check the post list or back-office record, and retry only after confirming that no corresponding record exists.
account_id for post, report, material-query, and publishing endpoints.page until meta.current_page >= meta.last_page.code, request_id, and key request parameters for troubleshooting.GET /v1/upload/url before assembling attachments.429, 502, and network timeouts.Q1: How do I determine whether a request succeeded?
Only HTTP 2xx with JSON code = 0 is successful. HTTP 4xx/5xx is a failure, but parse the response for code, error, data, and request_id. Treat HTTP 2xx with a non-zero code as a contract anomaly and record request_id.
Q2: How do I pass account_ids in the query string?
Repeat the bracketed key: account_ids[]=163956&account_ids[]=163955&account_ids[]=28.
Q3: How do I avoid HTTP 429?
Keep each API key below 120 requests per minute and implement throttling with exponential backoff. Prefer Retry-After; for product-sync cooldowns without that header, use data.next_allowed_at or the response message.
Q4: How do I confirm that an account is a TikTok Shop account?
Call /v1/account, verify app.title = "TikTokShop", and confirm status.value = 1.
Q5: Why does a product keyword return no results?
Some product titles are in English. Try the English title or omit keyword to retrieve all products and filter them locally.
Q6: Why is a new video not visible on TikTok immediately after the publishing request succeeds?
Success means the job was submitted. Upload, platform processing, and review are asynchronous. Save the publishing-record ID and request_id for troubleshooting.
Q7: What is the difference between upload_url and public_url?
upload_url is a temporary presigned OSS URL used only to upload the file. Use public_url as attachments[].url in the publishing request.
Q8: Why does the music endpoint not return volume fields?
The trending-music endpoint returns six media fields: url, uuid, cover, title, artist, and duration. Copy all six unchanged to extra.music, then add selection, music_volume, and original_sound_volume, for nine fields total. To play only the selected music on a TikTok Shop video, use music_volume = 50 and original_sound_volume = 0.
Q9: Should Pinterest boards and Reddit communities use id or uuid when publishing?
Use the integer data[].id as extra.category_id. uuid is the platform resource identifier, not the publishing category ID. Reddit flair is separate: when required, send both extra.flair.uuid and extra.flair.title.
Q10: Is an attachment url sufficient?
Yes. Each attachments[] item needs at least the public_url returned by the current OSS upload. Add thumb when a custom video cover is needed. The server fills in media type, size, dimensions, duration, and frame rate from OSS. External CDN URLs, upload_url, expired signed URLs, and URLs outside the configured SocialEcho OSS fail validation.
This document applies to SocialEcho OpenAPI v1, revised August 28, 2026. Build requests according to these fields and examples, and recheck platform publishing limits whenever the document version changes.