Last updated: 2026-08-28
This document is intended for development, QA, implementation, and automation engineers integrating with the SocialEcho external API. Its goal is to help you complete a working integration in the shortest possible time.
This document covers teams, accounts, authorization links, posts, reports, OSS uploads, Reddit/Pinterest publishing resources, TikTok Shop products and music, and cross-platform publishing under 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, then call other business endpoints.code in the response to identify the specific cause.| Field | Description |
|---|---|
| Base URL | https://api.socialecho.net |
| Authentication | Bearer Token (Team API Key) |
| Request header | Authorization: Bearer se_your_team_api_key |
| Optional request header | X-Lang: zh_CN or en |
| Rate limit | A single API Key supports up to 120 requests/minute |
Business parameters for all GET endpoints must be placed in the QueryString; requests must not include a body. Use bracket notation for array parameters, for example, account_ids[]=1&account_ids[]=2. When CloudFront receives a GET request with a body, it returns an HTML 403 Bad request directly.
200-299, and code in the response JSON must be 0. All endpoints listed in this document currently return HTTP 200 on normal success.400-599, and code in the response JSON is a non-zero business code. Business failures are no longer returned as HTTP 200.code, error.type, and data for detailed handling.2xx response, the client should still parse the JSON response body and record request_id; do not treat every non-2xx response as an unparseable network error.Successful response example:
{
"code": 0,
"message": "Success",
"data": {},
"request_id": "018f7f35-7c9a-7b82-a0f2-6a06b0b7d301"
}
Failed response example:
{
"code": 42200,
"message": "Request parameter validation failed",
"data": {
"account_id": ["Please select a TikTok Shop account"]
},
"error": {
"type": "invalid_request",
"reason": "Request parameter 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 header. Callers may provide a valid X-Request-Id themselves or use the server-generated value to correlate logs. Successful paginated responses also include meta.
| HTTP status | Standard business code | Meaning and recommended handling |
|---|---|---|
| 400 Bad Request | 40000 |
Request syntax, format, or basic parameter error; correct the request before submitting again |
| 401 Unauthorized | 40100 |
API Key is missing, invalid, or expired; check Authorization: Bearer ... |
| 403 Forbidden | 40300 |
Authentication succeeded but the operation is not permitted, for example, draft permission is missing; do not retry unchanged |
| 404 Not Found | 40400 |
The account, product, related authorization, or other resource does not exist, is unavailable, or does not belong to the current team |
| 405 Method Not Allowed | 40500 |
The HTTP method is unsupported; use the correct method indicated by the Allow response header |
| 409 Conflict | 40900 |
The current resource state conflicts with the operation; refresh the resource state before deciding whether to retry |
| 413 Payload Too Large | 41300 |
The request body or upload exceeds the server limit; reduce the file or request body |
| 419 Authentication Timeout | 41900 |
The session or security token has expired; this should normally not occur for Team API Key endpoints |
| 422 Unprocessable Entity | 42200 |
Field validation, platform publishing rules, or a recoverable business prerequisite failed; read the field errors in data |
| 429 Too Many Requests | 42900 |
The endpoint rate limit or product synchronization cooldown was triggered; read Retry-After first, or read data.next_allowed_at or the message when it is absent |
| 500 Internal Server Error | 50000 |
SocialEcho server error; retain request_id and contact support |
| 502 Bad Gateway | 50200 |
An upstream social platform call failed; retry later and retain request_id |
| 503/504 | 50300 / 50400 |
Service unavailable or upstream timeout; retry with backoff |
| Timeout/network error | No response body | Retry 2-3 times and retain a snapshot of the request parameters for troubleshooting |
Standard business codes use the form "HTTP status code x 100". A few historical business scenarios may retain a more specific custom non-zero code; this does not change the meaning of the HTTP status code, and callers should not rely on a single business code to determine success or failure.
Automatic retries are recommended only for 429, 502, 503, 504, and network timeouts. 400, 401, 403, 404, 405, 409, 413, and 422 usually require correcting the request, permissions, or resource state first.
The Base URL in all examples below is https://api.socialecho.net. Replace se_your_team_api_key with your Team API Key.
GET examples do not send Content-Type or a request body; when parameters are required, append them directly to the QueryString.
It is recommended to call this endpoint first to confirm the team context before retrieving business data.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
| X-Lang | header | No | string | zh_CN or en; default: zh_CN |
Request example (cURL)
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'
Response example
{
"code": 0,
"message": "Retrieved successfully",
"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"
}
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
| X-Lang | header | No | string | Response language |
| page | query | No | integer | Page number; if omitted, the server default applies |
| type | query | No | integer | 1 = authorized account, 2 = competitor account |
Request example (cURL)
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'
Response example
{
"code": 0,
"message": "Retrieved successfully",
"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": "Owned account"},
"status": {"value": 1, "label": "Normal"}
}],
"meta": {"total": 1, "current_page": 1, "last_page": 1, "per_page": 15},
"request_id": "018f7f35-7c9a-7b82-a0f2-6a06b0b7d301"
}
Get the social media platform authorization entry points available to the current team. The endpoint returns one or more connection methods per platform. Callers can select an authorization URL based on 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 |
Request example (cURL)
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'
Response example (excerpt; URLs redacted)
{
"code": 0,
"message": "Retrieved successfully",
"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"
}
Response fields:
| Field | Type | Description |
|---|---|---|
| data[].id | integer | Platform ID, corresponding to app.id in the account list |
| data[].title | string | Platform name |
| data[].connections | object[] | List of authorization entry points supported by the platform |
| data[].connections[].type | string | Authorization connection type, used to distinguish authorization modes within the same platform |
| data[].connections[].url | string | Authorization URL that can be opened directly; it may contain team context or one-time state parameters |
Currently returned platforms and connection types:
| 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 the authorization URL exactly as returned by the endpoint; do not rewrite it or discard query parameters. The URL may contain team-related state information, so long-term caching, public sharing, and writing it to ordinary business logs are not recommended. Call this endpoint again whenever authorization is required.
| HTTP status | Business code | Scenario |
|---|---|---|
| 200 | 0 |
Platform authorization entry points returned successfully |
| 401 | 40100 |
Team API Key is missing, invalid, or expired |
| 405 | 40500 |
Incorrect request method; use GET |
| 422 | 42200 |
A business prerequisite such as insufficient team credits failed |
| 500 | 50000 |
An unexpected server error occurred while generating authorization links |
| 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[] to pass an array of account IDs |
Request example (cURL)
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'
Response example
{
"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"
}
| 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 query range must not exceed the team's report permission |
| end_date | query | Yes | string | YYYY-MM-DD; cannot be later than today |
| time_type | query | Yes | integer | 1 = posts newly added within the date range, 2 = all historical posts |
| account_ids | query | No | integer[] | Repeat account_ids[] to pass an array of account IDs |
| group | query | No | string | Omitted = aggregate; day / app / account are grouping dimensions |
Request example (cURL)
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'
group changes the structure of data. Callers must parse the response according to the group in the request and must not assume that every grouping returns the same structure.
Response example (without group, aggregate)
{
"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"
}
Response structure (group=day, excerpt)
{
"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 item in data[] contains platform id, title, total, and increase. With group=account, each item contains account id, title, account, avatar, url, app, total, and increase. This endpoint currently defines only day, app, and account as grouping values; do not pass other values.
To retrieve daily data, add group=day to the request URL. Use group=app and group=account for platform and account grouping, respectively.
Get the presigned URL required to upload a file to OSS. The general flow is: obtain the upload URL -> upload the file using the returned HTTP method -> use public_url in the publishing endpoint's attachments.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
| X-Lang | header | No | string | Response language |
| content_type | query | Yes | string | MIME type of the file to upload; it must match the actual file |
| title | query | No | string | File name, up to 255 characters |
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.Request example (cURL)
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'
Response example
{
"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"
}
During upload, use the method, upload_url, and headers exactly as returned. upload_url is signed and time-limited; do not modify it, cache it, or use it for publishing.
File upload example
curl --request PUT 'upload_url_from_previous_response' \
--header 'Content-Type: video/mp4' \
--upload-file './product-video.mp4'
After a successful upload, the publishing endpoint must use the returned public_url, not the time-limited upload_url.
The upload endpoint supports audio files, but whether the publishing endpoint accepts an audio attachment still depends on the target platform and the publishing rules for type; a successful upload alone does not mean that the asset can be published.
This endpoint returns HTTP 200, code = 0 on success. Missing parameters, incorrect field types, or overlong fields return HTTP 422, code = 42200. An unexpected server error while generating the upload URL returns HTTP 500, code = 50000. Callers should submit only the MIME types listed above; the current server returns unsupported MIME types as HTTP 500, code = 50000.
Use this endpoint to select the community context before publishing Reddit content.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
| X-Lang | header | No | string | Response language |
| account_id | query | Yes | integer | Reddit social media 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'
Response example
{
"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 Reddit content, extra.category_id, if provided, must use the integer data[].id returned by this endpoint; do not pass uuid. Before submitting, check that attributes.permissions.release = true and confirm that the target type appears in attributes.permissions.type. The current community list does not guarantee that flair options are returned. If there is no confirmed valid flair, omit extra.flair instead of submitting an empty object.
Use this endpoint to select a board before publishing Pinterest content.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
| X-Lang | header | No | string | Response language |
| account_id | query | Yes | integer | Pinterest social media 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'
Response example
{
"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"
}
When publishing Pinterest content, extra.category_id must use the integer data[].id returned by this endpoint; do not pass the platform board uuid.
Get the products already synchronized for the specified TikTok Shop account. Before publishing TikTok Shop shoppable video or photo content, call this endpoint first to obtain the complete id, uuid, title, and thumb.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
| account_id | query | Yes | integer | TikTok Shop account ID, available from /v1/account |
| page | query | No | integer | Page number; default: 1 |
| per_page | query | No | integer | Items per page, from 1 to 100; default: 20 |
| keyword | query | No | string | Product title keyword, up to 500 characters |
Request example (cURL)
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'
Response example
{
"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 that the product is currently available for publishing. If a Chinese keyword does not return a match, use the product's English title or omit keyword to retrieve all products.
| HTTP status | Business code | Scenario |
|---|---|---|
| 200 | 0 |
Product list returned successfully |
| 404 | 40400 |
TikTok Shop account does not exist, is unavailable, unauthorized, or does not belong to the current team |
| 422 | 42200 |
account_id, pagination, or keyword parameters are invalid |
| 500 | 50000 |
An unexpected server error occurred while querying products |
Request that SocialEcho asynchronously refresh the products for the specified TikTok Shop account. This endpoint only indicates whether the synchronization task entered the queue successfully; it does not indicate that the products have finished refreshing. To avoid duplicate synchronization, the same account has an approximately 60-minute cooldown period.
| 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}'
Successful response:
{
"code": 0,
"message": "Product synchronization task submitted",
"data": {
"account_id": 123456,
"status": "queued"
},
"request_id": "018f7f35-7c9a-7b82-a0f2-6a06b0b7d301"
}
| HTTP status | Business code | Scenario |
|---|---|---|
| 200 | 0 |
Synchronization task entered the queue |
| 404 | 40400 |
Account does not exist, is unavailable, unauthorized, or does not belong to the current team |
| 422 | 42200 |
account_id is missing or the account type does not support product synchronization |
| 429 | 42900 |
Synchronization is in progress or the cooldown period is still active; defer the retry according to data.next_allowed_at, Retry-After when present, or the message |
| 500 | 50000 |
Synchronization task submission failed; retain request_id and contact support |
Get the music categories 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'
Response example (excerpt)
{
"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"
}
This endpoint returns HTTP 200, code = 0 on success. Business prerequisites such as insufficient credits return HTTP 422, code = 42200; an unexpected server error returns HTTP 500, code = 50000. Authentication failures, incorrect request methods, and other cases follow the general status code rules in Section 4.
Get available music from the TikTok commercial music library. account_id can be the ID of a TikTok Shop account that is currently in a normal state for the team, or a TikTok authorized account ID directly. When a TikTok Shop account is provided, the server resolves its associated or available TikTok authorized account to query music.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
| account_id | query | Yes | integer | TikTok Shop or TikTok authorized account ID |
| country_code | query | No | string | Two-letter country code, such as US; default: US |
| genre | query | No | string | Category value obtained from the music genres endpoint; default: ALL |
| date_range | query | No | string | 1DAY, 7DAY, 30DAY, or 90DAY; default: 30DAY |
Request example (cURL)
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'
Response example
{
"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"
}
The returned fields in data[] are:
| Field | Type | Description |
|---|---|---|
| uuid | string | Unique music identifier; pass it as extra.music.uuid when publishing |
| title | string | Music title |
| artist | string | Music author or performer |
| url | string | Music preview URL |
| cover | string | Music cover URL |
| duration | integer | Music duration in seconds |
selection, music_volume, and original_sound_volume are not response fields from the music list endpoint; they are music control parameters set by the caller when publishing. When publishing with selected music, copy the six fields url, uuid, cover, title, artist, and duration returned by the music list into extra.music without changing their values, then add the three publishing control fields selection, music_volume, and original_sound_volume. Do not pass only the music UUID or reduce the object to four fields.
Complete music object example
{
"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 | Business code | Scenario |
|---|---|---|
| 200 | 0 |
Trending music returned successfully |
| 404 | 40400 |
TikTok Shop account does not exist, or no TikTok authorized account is available for querying music |
| 422 | 42200 |
account_id, country, category, or date range parameters are invalid |
| 429 | 42900 |
Endpoint rate limit triggered; retry after Retry-After |
| 502 | 50200 |
An upstream service such as the TikTok commercial music library failed |
| 500 | 50000 |
Another unexpected server error occurred while querying music |
Cross-platform publishing. Fields such as type, extra, and attachments are platform-specific; complete them according to the target platform.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
| X-Lang | header | No | string | Response language |
| account_id | body | Yes | integer | Social media account ID used for publishing |
| type | body | Yes | string | Publishing type; values depend on the platform |
| status | body | Yes | integer | 0 = draft, 1 = publish |
| scheduled_at | body | No | string | Scheduled time; used only when status = 1; publish immediately when omitted; if no timezone is included, parse it using the team timezone |
| comment | body | No | string or string[] | Comment content; a single string is automatically converted to an array. Arrays are recommended. Up to 10 comments per platform; some platforms do not support comments |
| content | body | No | string | Post content; required by some platforms |
| extra | body | Conditionally required | object | Platform-specific extension fields; complete them according to the target platform and type |
| attachments | body | Conditionally required | object[] | Attachment list; required, optional, or prohibited according to platform rules. Each item must contain at least the url of an uploaded file. A video cover can be supplied through thumb |
The url and thumb in attachments must be file addresses recognized by the current SocialEcho OSS configuration. It is recommended to use only the public_url returned by GET /v1/upload/url. The server automatically parses attachment type, dimensions, size, duration, and frame rate from the OSS file; callers do not need to submit these metadata fields.
Example type values:
reels / post / stories.shorts / video.reels / post / stories.short_post / long_post.post.video / photo.video / photo.post.text / link / media.post.post.The following are the main validation rules for the current external publishing endpoint. File sizes are per-attachment limits. The server automatically parses and validates media dimensions, frame rate, duration, and aspect ratio from OSS.
| Platform / type | content |
Key extra fields |
Attachment requirements |
|---|---|---|---|
Facebook reels |
Optional, up to 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 one of content or attachments; 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, up to 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, up to 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, up to 3 usernames |
Exactly 1 video; max 300 MiB, 23-60 fps, 3-900 seconds, 9:16 ratio |
Instagram post |
Optional, max 2,200 characters and 30 hashtags | collaborators optional, up to 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, up to 4 images, GIFs, or videos |
X long_post |
Optional, max 25,000 characters | No required extension fields | Optional, up to 4 images, GIFs, or videos |
LinkedIn post |
Optional, max 3,000 characters | No required extension fields | Optional, up to 20 total attachments; max 20 images/GIFs and 1 video |
TikTok video |
Optional, max 2,200 UTF-16 code units | draft boolean required; is_ai_generated and music optional; title not supported |
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 boolean required; optional title, max 90 UTF-16 code units; music optional |
1-35 jpg / jpeg / webp images; max 20 MiB each |
Pinterest post |
Optional, max 500 characters | Required integer category_id, from the board list's 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 attachments; max 20 images/GIFs and 1 video |
Threads post |
Optional, max 500 characters | No required extension fields | Optional, up to 20 images or videos; GIFs not supported |
Telegram post |
Optional, max 4,096 characters | No required extension fields | Optional, up to 10 images or videos; comment not supported |
YouTube extra.tags must be a string array: it must not contain empty values, duplicates, or control characters. After applying YouTube's comma and quotation mark counting rules, the total length must not exceed 500. A YouTube video cover is passed through attachments[0].thumb; only jpg, jpeg, and png are supported, with a maximum size of 2 MiB.
Instagram extra.collaborators must be an array of username strings and may include or omit the leading @. Usernames may contain only letters, numbers, periods, and underscores, and must not be duplicated. When Reddit does not need flair, omit extra.flair completely. When flair is provided, both uuid and title are required.
Generic request example (cURL)
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
Before publishing, complete these steps in order:
/v1/account to obtain the ID of a TikTok Shop account in a normal state./v1/tiktokshop/products to obtain the product to attach./v1/upload/url and upload the video or images to OSS.public_url from the upload response.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": []
}
The OSS addresses in the example above illustrate the field format. In actual requests, replace them with the public_url returned by the current upload request. Product fields must use the 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": []
}
General TikTok Shop field requirements:
account_id must be a TikTok Shop account in a normal state and belonging to the current team.type supports only video or photo.extra.title is required, with a maximum of 30 characters. It supports only Unicode letters, numbers, and spaces; punctuation is not supported, although letters from languages such as Chinese are allowed.extra.product is required. id, uuid, title, and thumb must be taken directly from the product list endpoint.status = 1.extra.music is optional. When music is selected, all nine fields must be provided: url, uuid, cover, title, artist, duration, selection, music_volume, and original_sound_volume.extra.music.url, uuid, cover, title, artist, and duration must use the original values from the current music query result. Do not construct, truncate, or reduce them to only the UUID.extra.music.selection supports none, trending_clip, and full_track. When it is not none, a complete music object is required.extra.music.music_volume and extra.music.original_sound_volume must be integers from 0 to 100; the example values are 50 and 0, respectively.extra.music may be omitted or set to {"selection":"none"}. Do not pass only the UUID for selected music.status = 1 with no scheduled_at means submit for immediate publishing.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. For files of 10 MiB or larger, use mp4, mov, or webm.extra.is_ai_generated is optional and must be a boolean.TikTok Shop photo requirements:
content is optional; when provided, it must not exceed 5,000 UTF-16 code units.attachments must contain at least one image and may contain images only. The current endpoint does not set an image count limit, but TikTok Shop platform limits still apply.jpg, jpeg, png, webp, heic, and bmp; each image must be larger than 0 and no larger than 10 MiB.9:16 and 16:9.Response example
{
"code": 0,
"message": "Submitted successfully",
"data": {"id": 183308},
"request_id": "018f7f35-7c9a-7b82-a0f2-6a06b0b7d301"
}
data.id in the response is the SocialEcho publishing record ID. HTTP 200 with business code = 0 means that the task was submitted successfully; it does not mean that TikTok Shop has completed final publishing. Platform publishing, video processing, and review are asynchronous.
TikTok Shop publishing endpoint statuses:
| HTTP status | Business code | Scenario |
|---|---|---|
| 200 | 0 |
Publishing task submitted successfully |
| 403 | 40300 |
The team does not have draft permission when status = 0 |
| 404 | 40400 |
The team, account, or account-related resource does not exist, or the account does not belong to the current team |
| 422 | 42200 |
Field validation, attachments, products, music, TikTok Shop publishing rules, business prerequisites, or a recoverable runtime failure in the publishing workflow |
| 500 | 50000 |
Another unexpected server error |
The publishing endpoint submits the asynchronous task only after creating the record. Therefore, when HTTP 422 or 500 is returned during submission, it is not guaranteed that no publishing record was created. Do not resubmit immediately. First save request_id, confirm through the post list or the backend record whether a corresponding publishing record was created, and then decide whether to retry to avoid duplicate publishing.
account_id to the post, report, resource query, and publishing endpoints to avoid using an account that does not belong to the current team.page consistently and stop when the response satisfies meta.current_page >= meta.last_page.code, request_id, and key request parameters for production troubleshooting.GET /v1/upload/url to upload assets, then build attachments.429, 502, and network timeouts.Q1: How do I determine whether an API call succeeded?
A: It is successful only when the HTTP status code is 2xx and code = 0 in the JSON. All HTTP 4xx/5xx responses are failures, but the response body should still be parsed to obtain code, error, data, and request_id. If an HTTP 2xx response contains a non-zero code, treat it as a contract violation and record request_id.
Q2: How do I pass account_ids in the QueryString?
A: Repeat the parameter key with brackets, for example, account_ids[]=163956&account_ids[]=163955&account_ids[]=28.
Q3: How can I avoid triggering 429?
A: Keep a single API Key below 120 requests per minute and configure throttling and exponential backoff. Prefer waiting according to Retry-After. If the product synchronization cooldown does not return that header, wait according to data.next_allowed_at or the response message.
Q4: How do I confirm that an account is a TikTok Shop account?
A: Call /v1/account, check whether app.title in the returned item is TikTokShop, and confirm that status.value = 1.
Q5: What should I do if a product keyword search returns no results?
A: Some product titles are in English. Use an English keyword, or omit keyword to retrieve all products and filter them afterward.
Q6: Why is the new video not immediately visible on the TikTok profile after the publishing endpoint succeeds?
A: Publishing endpoint success only means that the task was submitted. Video upload, TikTok Shop publishing, and platform review are asynchronous and may take time. Keep the publishing record ID and request_id from the response for troubleshooting.
Q7: What is the difference between upload_url and public_url in the upload response?
A: upload_url is a time-limited OSS presigned upload URL used only to upload the file. public_url is the file address that the publishing endpoint should use as attachments[].url.
Q8: Why does the music endpoint not return volume fields?
A: The trending music endpoint returns six music asset fields: url, uuid, cover, title, artist, and duration. After selecting music, the caller must copy these six original values into extra.music and add the three publishing control fields selection, music_volume, and original_sound_volume, for a total of nine fields. When a TikTok Shop video plays only the selected music, you can use music_volume = 50 and original_sound_volume = 0.
Q9: Should I pass id or uuid when publishing to a Pinterest board or Reddit community?
A: extra.category_id must be the integer data[].id returned by the list endpoint. uuid is the platform resource identifier, not the category_id for the publishing endpoint. Reddit flair is the exception: when flair is required, pass extra.flair.uuid and extra.flair.title separately.
Q10: Is passing only url in a publishing attachment sufficient?
A: Yes. Each item in attachments[] needs at least the public_url from the current OSS upload response. For a custom video cover, you can also pass thumb. The server reads OSS metadata and fills in attachment type, size, dimensions, duration, and frame rate. External CDN URLs, upload_url, expired signed URLs, or addresses outside SocialEcho OSS fail validation.
This document corresponds to SocialEcho OpenAPI v1 and was revised on 2026-08-28. Integrators should assemble requests according to the fields and examples in this document and recheck platform publishing limits when upgrading the documentation version.