Build on
Social Factory.
Order from your app.
Order X accounts and Telegram groups from your own product. Follow every worker, read the conversation, approve, get signed webhooks. The same API the app runs on.
From key to order, in three calls.
Create a key in the app, under API. Every call sends it as a bearer token. Orders are paid from your account's wallet, like in the app.
Describe the project
Name, bio, picture, the handles you want. Once.
curl -X POST $BASE/projects \ -H "Authorization: Bearer $KEY" \ -H "content-type: application/json" \ -d '{"name":"Nova","ticker":"NOVA", "bio":"Swap any token in one tap.", "pfp_url":"https://.../nova.png", "handles":["novafun","novaapp"]}'
Order a mission
An X account or a Telegram group. It goes to the workers at once.
curl -X POST $BASE/projects/1000021/missions \ -H "Authorization: Bearer $KEY" \ -H "Idempotency-Key: nova-x-1" \ -d '{"kind":"x"}' # 402 if the wallet cannot cover it
Follow it, then approve
The deliverable, the timeline, every message with the worker.
curl $BASE/missions/52 \ -H "Authorization: Bearer $KEY" curl -X POST $BASE/missions/52/approve \ -H "Authorization: Bearer $KEY"
Know the moment it moves.
Set a URL in the app. Each time a mission changes (claimed, delivered, paid, a first post, an authorization), we POST it, signed with your secret. Retried every 20 seconds until you answer 2xx.
- X-XFactory-Signature: hex HMAC-SHA256 of the raw body
- Event mission.updated with the full mission object
- The secret is shown once, roll it anytime
import { createHmac, timingSafeEqual } from "node:crypto"; export function verify(raw, header, secret) { const mac = createHmac("sha256", secret).update(raw).digest("hex"); return header?.length === mac.length && timingSafeEqual(Buffer.from(header), Buffer.from(mac)); } // body: { event: "mission.updated", at, mission: { id, status, result, ... } }
Reference.
Base URL https://api.socialfactory.app/v1. JSON in, JSON out. Errors come as {"error": "..."} with a meaningful status.
| Method | Path | What it does |
|---|---|---|
| GET | /me | your account, mission counts, prices |
| POST | /projects | create a project: name, ticker, bio, pfp_url, banner_url, handles, website |
| GET | /projects | your projects |
| PUT | /projects/{id} | update the snapshot, only the fields you send |
| POST | /projects/{id}/missions | order: {"kind": "x" | "tg"}, optional handle and name; Idempotency-Key supported |
| POST | /projects/{id}/launch | {"mint"}: the X worker posts the contract address |
| GET | /missions | your missions, with messages_count and last_message_at |
| GET | /missions/{id} | everything: deliverable, evidence, messages, payout, timeline, rating; ?review=1 adds a live review |
| GET | /missions/{id}/messages | the conversation with the worker |
| GET | /missions/{id}/review | the bot reads the account or the group now |
| POST | /missions/{id}/approve | pay the worker from your wallet |
| POST | /missions/{id}/reject | close it, no payout |
| POST | /missions/{id}/cancel | {"reason"}, before delivery |
| GET | /workers | your workers ranked: rating, deliveries, speed |
Statuses
open · claimed · submitted · paid · rejected · cancelled
Funds
An order reserves its highest cost. 402 when your wallet cannot cover it: deposit and retry.
Keys
One live key per account. Rolling it ends the old one at once. Keep it on your server.