Quickstart
From an API key to a scheduled post, in one sitting.
Afilipost was written API first: everything the panel does is an endpoint you can call. This page takes you from an API key to a scheduled post.
Authentication
Every request carries your key as a bearer token. Keys are issued in the panel (Keys screen) and shown once — we store only a SHA-256 digest, so a leaked database does not leak keys.
Authorization: Bearer yay_·············
Content-Type: application/json Base address: https://api.afilipost.com — the same routes also answer without the /api prefix, so a client written against a Zernio-shaped base works unchanged.
The shortest path to a published post
- Ask for an upload address with /v1/media/presign and PUT your file to it — the bytes go straight to storage, never through the API.
- Create the post with /v1/posts, pointing mediaItems at the publicUrl you were given. One post can target several accounts.
- Register a webhook and receive post.published the moment it goes out — or poll /v1/posts/{id} until platformPostId appears.
- Attach the comment → DM rule with /v1/comment-automations.
Quickstart in Python
The whole publish path, standard library only — no SDK to install:
import json, urllib.request
BASE = "https://api.afilipost.com/api"
KEY = "yay_………"
def call(path, payload=None, method="GET"):
data = json.dumps(payload).encode() if payload else None
req = urllib.request.Request(BASE + path, data=data, method=method,
headers={"Authorization": f"Bearer {KEY}",
**({"Content-Type": "application/json"} if data else {})})
with urllib.request.urlopen(req, timeout=60) as r:
return json.loads(r.read() or "{}")
# 1) yükleme adresi al, dosyayı DOĞRUDAN depoya gönder
grant = call("/v1/media/presign",
{"filename": "reel.mp4", "contentType": "video/mp4"}, "POST")
with open("reel.mp4", "rb") as f:
put = urllib.request.Request(grant["uploadUrl"], data=f.read(),
method="PUT", headers={"Content-Type": "video/mp4"})
urllib.request.urlopen(put, timeout=600)
# 2) gönderiyi planla
account = call("/v1/accounts?platform=instagram")["accounts"][0]
post = call("/v1/posts", {
"content": "Bugünün reposu 🚀",
"mediaItems": [{"type": "video", "url": grant["publicUrl"],
"filename": "reel.mp4", "mimeType": "video/mp4"}],
"platforms": [{"platform": "instagram", "accountId": account["_id"],
"platformSpecificData": {"firstComment": "Link için REPO yaz"}}],
"scheduledFor": "2026-08-25T19:40:00.000Z",
"idempotencyKey": "ilk-deneme-1",
}, "POST")
print(post["post"]["_id"], post["post"]["status"]) Key concepts
- Post and targets. One post carries the content; each connected account it goes to is a target with its own status. Instagram can succeed while YouTube is rate-limited, and the API tells you which is which.
- Idempotency. Send idempotencyKey on /v1/posts and a retried request returns the existing post instead of creating a duplicate.
- No passwords, ever. Accounts connect through each platform's own OAuth screen; the API only ever sees tokens, and they are encrypted at rest.