Post a video to a group
Upload a video and its thumbnail, then post it to a group with a caption, mentions, questions, or link-out cards.
Posting takes two steps: upload the files to Genuin's media storage through signed URLs, then call this endpoint with the file names. The post appears in the group feed and the community right away, under the account behind your access token. That account has to be allowed to post in the group by its "who can post" setting. See Generate an access token for the token.
Endpoint
POST /api/thirdparty/users/conversation/reply
| Environment | Base URL |
|---|---|
| Production | https://api.begenuin.com |
| QA | https://api.qa.begenuin.com |
Send the token as a bearer token in the Authorization header, and the fields as a JSON body with the Content-Type: application/json header.
Step 1: Upload the video and thumbnail
Request a signed URL for each file, then send the bytes to it with a PUT. Both calls take the same bearer token.
curl -X POST https://api.begenuin.com/api/v3/users/video/upload/create_upload_url \
-H "Authorization: Bearer {{GN_ACCESS_TOKEN}}" \
-H "Content-Type: application/json" \
-d '{ "contentType": "video/mp4", "path": "temp_video/{{VIDEO_FILE}}" }'{
"code": 200,
"message": "Upload URL generated successfully.",
"data": { "uploadURL": "https://media-bucket.s3.amazonaws.com/temp_video/{{VIDEO_FILE}}?X-Amz-Signature=..." }
}curl -X PUT "{{UPLOAD_URL}}" -H "Content-Type: video/mp4" --data-binary @recap.mp4Repeat for the thumbnail with "contentType": "image/jpeg" and "path": "uploads/thumbnails/{{THUMB_FILE}}".
| Rule | Detail |
|---|---|
| Paths | Videos go under temp_video/, thumbnails under uploads/thumbnails/. The file name after the folder is what you pass in step 2. |
| File names | Make each one unique, such as <uuid>_<timestamp>.mp4. A video file name that was posted before is rejected in step 2. |
| Content types | video/, image/, audio/, and text/. Anything else returns 412 with code 5174. |
| Expiry | The signed URL is valid for one PUT and a short time. Request it right before the upload, and send the same Content-Type you asked for. |
Step 2: Post the video
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| chat_id | string | Required | UUID of the group, from Create a group in a community. |
| video_name | string | Required | The file name uploaded under temp_video/. |
| thumbnail_name | string | Required | The file name uploaded under uploads/thumbnails/. |
| aspect_ratio | string | Required | Such as "9:16". |
| duration | string | Required | Length in seconds, such as "8". |
| resolution | string | Required | Such as "1080x1920". |
| size | string | Required | File size, such as "5MB". |
| description_text | string | Optional | Caption, up to 2,000 UTF-16 code units. Requires description_data. |
| description_data | string | Required with description_text | JSON string of the caption split into text and mentions: ["Hi, this is ", {"user_id": "<uuid>"}, " in ", {"community_id": "<uuid>"}]. |
| questions | array of strings | Optional | Ids of questions to attach, so members answer them in replies. |
| link | string | Optional | A URL shown with the video. Can't be combined with linkouts. |
| linkouts | array | Optional | One or more link-out cards. See Link-outs. |
| meta_data | object | Optional | Free-form, such as {"topic": "Race day"}. |
| message_id | string | Optional | A UUIDv4 to use as the post's id. A reused id is rejected. |
| source | string | Optional | Where the file came from: device, youtube, tiktok, instagram, or ai. |
| is_ai_generated | boolean | Optional | Marks the post as AI-generated. |
| ingestion_source | integer | Optional | 1 uploads, 2 Clip It, 3 social import. Allowed only with is_ai_generated or is_ai_generated_video. |
| video_path, thumbnail_path, is_ai_generated_video, is_ai_generated_thumbnail | string, boolean | Optional | For media produced by Genuin's generation flow: the source folders in the generation bucket, and the flags that copy them into place. |
| platform | string | Optional | mobile or web, used to validate link-out URLs. |
| language | string | Optional | Two-letter code, such as en. |
| location | object | Optional | {"latitude", "longitude", "id", "name"}, all required when sent. |
| brand_context | array | Optional | [{"type": "...", "id": "..."}] entries that tie the post to brand objects. |
Link-outs
A link-out is a card on the video that opens a URL. Each entry in linkouts has an optional style (integer), cta_text, cta_link, cta_metadata, and a required links array with at least one link:
| Field | Type | Required | Description |
|---|---|---|---|
| position | integer | Required | Order of the link in the card. |
| link | string | Required | The URL. Genuin validates it against your brand's allowed domains and returns 412 with the failing URLs when one is rejected. |
| image | string | Optional | File name of a card image uploaded to Genuin's media storage. |
| title | string | Optional | Card title. |
| cta_text | string | Optional | Button label, 1 to 24 characters. |
| metadata | object | Optional | Free-form. |
Request
curl -X POST https://api.begenuin.com/api/thirdparty/users/conversation/reply \
-H "Authorization: Bearer {{GN_ACCESS_TOKEN}}" \
-H "Content-Type: application/json" \
-d '{
"chat_id": "{{CHAT_ID}}",
"video_name": "{{VIDEO_FILE}}",
"thumbnail_name": "{{THUMB_FILE}}",
"aspect_ratio": "9:16",
"duration": "8",
"resolution": "1080x1920",
"size": "5MB",
"description_text": "Finish line at the Ridge 50K",
"description_data": "[\"Finish line at the Ridge 50K\"]"
}'Returns
Returns 200 OK with the group card and the new post in chats. The post is visible in the group feed as soon as the response arrives.
Response
{
"code": 200,
"message": "Reply Sent Successfully",
"data": {
"chat_id": "1a14b9e2-9552-48d5-b1e3-a1ba237891cf",
"type": 4,
"no_of_views": 0,
"settings": { "discoverable": true },
"share_url": "https://community.example.com/community/trail-runners/race-recaps",
"is_offline": false,
"group": { "group_id": "f67c89d0-9abc-4abc-bdef-56789abcf456", "group_name": "Race recaps" },
"brand_id": 1429,
"is_subscriber": false,
"member_info": { "status": 1, "role": 1 },
"chats": [
{
"owner": { "member_id": "0bf977ed-4887-4056-a8f4-1f0de71101f1", "nickname": "examplebrand" },
"user_id": "0bf977ed-4887-4056-a8f4-1f0de71101f1",
"thumbnail_url": "https://media.begenuin.com/uploads/thumbnails/{{THUMB_FILE}}",
"video_url": "https://media.begenuin.com/temp_video/{{VIDEO_FILE}}",
"link": null,
"duration": "8",
"size": "5MB",
"aspect_ratio": "9:16",
"resolution": "1080x1920",
"conversation_id": "a5006e51-8950-4e1f-9b9a-65714720b0a6",
"conversation_at": 1760543999000,
"is_read": true,
"is_reply": false,
"questions": [],
"meta_data": {},
"no_of_views": 0,
"no_of_comments": 0,
"share_url": "https://community.example.com/v/finish-line-at-the-ridge-50k?l=11d88992ba811475"
}
]
}
}chats[0].conversation_id is the post's id, and chats[0].share_url is its public link. video_url and thumbnail_url are the CDN URLs of the files you uploaded.
Errors
Every error response carries an HTTP status, a string code, a message, and a data object. Match on code.
| HTTP status | code | Cause | Fix |
|---|---|---|---|
| 400 Bad Request | none | A field failed validation, such as a chat_id that isn't a UUID. The body is {"data": {}} with no code or message. | Check the Parameters table. |
| 403 Forbidden | 5230 | The group's "who can post" setting excludes the token's account. Message: XXXX-[Access Denied].. | Post from a group member, or change the setting with Update a group and its members. |
| 403 Forbidden | 5243 | The group belongs to a brand outside your network. | Use a group under your brand. |
| 404 Not Found | 5044 | The group doesn't exist or is deleted. | Check chat_id. |
| 404 Not Found | 5235 | Link-out validation needs the brand, and it isn't active. | Contact the Genuin team. |
| 409 Conflict | 5057 | video_name or message_id was posted before. Message: You have already replied to this video.. | Upload under a new file name, and use a new message_id. |
| 412 Precondition Failed | 5166 | A link-out URL isn't allowed. data.err_msg lists each URL with the reason. | Use URLs on your brand's allowed domains. |
| 412 Precondition Failed | 5174 | Step 1 was called with a content type outside video, image, audio, or text. | Send a supported contentType. |
| 422 Unprocessable Entity | 5023 | Step 1 couldn't sign the URL. Message: Could not fetch credentials.. | Retry. If it persists, contact the Genuin team. |
| 422 Unprocessable Entity | 5059 | The post couldn't be saved. Message: Error in sending reply.. | Retry once. If it persists, contact the Genuin team with the request timestamp. |
Limitations
- One post per file: A
video_namecan be posted once. Upload again under a new name to post the same clip twice. - No edit or delete: There's no third-party endpoint to change or remove a post. Use Brand Control Center under Curate.
- Rate limit: There's no rate limit on this endpoint or the signed-URL endpoint.

