Sikio API · v1
Media assets: defaults and overrides
This guide applies only to media templates. A text template does not need a media ID or an upload.
Use the template’s default asset
Omit header:media_id to use the attachment saved when the template was created in Sikio. For an older or externally created template, Sikio may prepare the original asset when a supported provider download is available. If no usable default exists, supply an explicit sendable media ID.
Override one message
Supply header:media_id in template_variables. This affects that message only; it does not change the template’s saved default. An explicitly blank ID is invalid. The actual resolved asset is retained with the sent conversation message.
{
"template_variables": {
"body:1": "Amina",
"header:media_id": "SENDABLE_WHATSAPP_MEDIA_ID"
}
}Upload a new asset when needed
Use whatsapp:send on the same channel. Submit exactly one multipart field named file. Let your HTTP client set the multipart boundary.
Replace CHANNEL_ID with your channel’s id. Use a local PNG file at ./header-image.png, or change the file and MIME type together.
curl --fail-with-body \
--user 'YOUR_API_KEY:YOUR_API_SECRET' \
--write-out '\nHTTP %{http_code}\n' \
--request POST \
--form 'file=@./header-image.png;type=image/png' \
'https://stage.api.ictlife.com/v1/integrations/whatsapp/channels/CHANNEL_ID/media'import { readFile } from 'node:fs/promises';
import { basename } from 'node:path';
const filePath = './header-image.png';
const mimeType = 'image/png';
const file = await readFile(filePath);
const form = new FormData();
form.append('file', new Blob([file], { type: mimeType }), basename(filePath));
const credentials = Buffer.from('YOUR_API_KEY:YOUR_API_SECRET').toString('base64');
const response = await fetch("https://stage.api.ictlife.com/v1/integrations/whatsapp/channels/CHANNEL_ID/media", {
method: 'POST',
headers: {
Authorization: 'Basic ' + credentials,
},
body: form,
});
const text = await response.text();
if (!response.ok) throw new Error(`HTTP ${response.status}: ${text}`);
console.log(response.status, text ? JSON.parse(text) : null);import base64, json
import urllib.request, urllib.error
from pathlib import Path
import uuid
credentials = base64.b64encode(b'YOUR_API_KEY:YOUR_API_SECRET').decode()
headers = {'Authorization': 'Basic ' + credentials}
file = Path('./header-image.png')
mime_type = 'image/png'
boundary = 'sikio-' + uuid.uuid4().hex
filename = file.name.replace('"', '').replace('\r', '').replace('\n', '')
prefix = (f'--{boundary}\r\nContent-Disposition: form-data; name="file"; filename="{filename}"\r\n'
f'Content-Type: {mime_type}\r\n\r\n').encode()
body = prefix + file.read_bytes() + f'\r\n--{boundary}--\r\n'.encode()
headers['Content-Type'] = 'multipart/form-data; boundary=' + boundary
request = urllib.request.Request("https://stage.api.ictlife.com/v1/integrations/whatsapp/channels/CHANNEL_ID/media", method='POST', headers=headers, data=body)
try:
with urllib.request.urlopen(request, timeout=30) as response:
text = response.read().decode()
print(response.status, json.loads(text) if text else None)
except urllib.error.HTTPError as error:
raise SystemExit(f'HTTP {error.code}: {error.read().decode()}'){
"media_id": "WHATSAPP_MEDIA_ID",
"channel_id": 42,
"mime_type": "image/png",
"size_bytes": 24576
}Use the returned media_id in a subsequent template send on that channel. Uploading alone sends no message and does not create or modify a template.
| Asset | Allowed file | Maximum size |
|---|---|---|
| Image | JPEG / PNG | 5 MiB |
| Video | MP4 | 16 MiB |
| Document | 100 MiB |
The file type must match the approved header. Sikio checks bytes and size; WhatsApp performs further compatibility validation. URLs, multiple files and extra multipart fields are rejected. A template approval upload handle is not a sendable media ID.
Uploads and retries
Bound upload concurrency. The current per-instance limits are two concurrent uploads per credential and eight in total. HTTP 429 includes Retry-After: 2. Uploads are not idempotent, so a retry may create another media object. Reuse a successful ID for message retries instead of uploading again.
Media IDs can expire or be removed by WhatsApp; re-upload when needed. Sikio does not automatically refresh unavailable saved assets. A message replay with the original key and payload uses the recorded send request rather than resolving the default again.
For carousel assets use the appropriate card_1:header:media_id key. Return to template parameters.