Quick Start
The Attention Factory API is rentals-and-actions first. You rent a real, verified social account for a whole month, then submit actions (posts, comments, likes, follows, branding changes) against it. This guide walks through your first rental in five steps.
1. Sign up and get your API key
Create your account on the dashboard, then generate an API key from the API Keys page. Every request below requires it in theAuthorization header.
2. Create a rental
Pick a platform and a duration (in whole months). Optionally supply filters, a branding preset, or an opt-in warming niche. The response is always 202 Accepted — the rental may be active immediately, orwarming while the account is prepared.
curl -X POST https://api.attentionfactory.com/v1/rentals \
-H "Authorization: Bearer af_live_sk_..." \
-H "Content-Type: application/json" \
-d '{
"platform": "instagram",
"months": 1,
"auto_renew": true
}'{
"id": "4e1a5c98-1d23-4c9e-b3a7-0fdbc2a6e1b3",
"anonymized_id": null,
"platform": "instagram",
"rental_start": null,
"rental_end": null,
"monthly_rate": "99.00",
"credits_charged": "99.00",
"auto_renew": true,
"status": "warming",
"expires_pending_at": "2026-05-02T12:00:00Z",
"branding_preset": null,
"created_at": "2026-04-18T12:00:00Z",
"profile": null
}3. Wait for activation
Poll the rental or register a webhook for rental.active. Once status flips toactive with a non-null anonymized_id, the account is yours for the rental window. On active rentals, the response includes a live profile object with the account's real username, display name, avatar, and follower counts.
curl https://api.attentionfactory.com/v1/rentals/4e1a5c98-1d23-4c9e-b3a7-0fdbc2a6e1b3 \
-H "Authorization: Bearer af_live_sk_..."{
"id": "4e1a5c98-1d23-4c9e-b3a7-0fdbc2a6e1b3",
"anonymized_id": "7c2d9f5b-e48a-4c11-8b3f-91c2e4d8a6b7",
"platform": "instagram",
"rental_start": "2026-04-18T12:30:00Z",
"rental_end": "2026-05-18T12:30:00Z",
"monthly_rate": "99.00",
"credits_charged": "99.00",
"auto_renew": true,
"status": "active",
"expires_pending_at": null,
"branding_preset": null,
"created_at": "2026-04-18T12:00:00Z",
"profile": {
"username": "launchpad_labs",
"display_name": "Launchpad",
"avatar_url": "https://cdn.example.com/avatars/launchpad.jpg",
"follower_count": 2340,
"following_count": 180,
"post_count": 47
}
}4. Submit an action
Actions are scoped to a rental + platform. The body carries atype (e.g.post.image) and action-specificparams. The rental must beactive.
curl -X POST https://api.attentionfactory.com/v1/rentals/$RENTAL_ID/instagram/actions \
-H "Authorization: Bearer af_live_sk_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: launch-post-001" \
-d '{
"type": "post.image",
"params": {
"caption": "Our new launch is live.",
"media_url": "https://cdn.example.com/launch.jpg"
}
}'5. Track completion via webhook
Register a webhook once and receive action status transitions (action.assigned, action.submitted, action.verified, etc.) in near-real-time.
curl -X POST https://api.attentionfactory.com/v1/webhooks \
-H "Authorization: Bearer af_live_sk_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://acme.com/webhooks/af",
"events": ["rental.active", "action.verified", "action.failed"],
"secret": "whsec_your_signing_secret"
}'Authentication
All API requests require an API key passed in the Authorization header.
Authorization: Bearer af_live_sk_...
API Key Format
API keys follow the format af_live_sk_... for production and af_test_sk_... for testing. Keys are generated and revoked from the API Keys page in the dashboard.
Platforms
Discovery endpoints for supported platforms, the actions they expose, and the niches available for opt-in warming. Call these before creating a rental to validate input client-side.
Endpoints
/v1/platformsList supported platforms
/v1/platforms/{platform}/capabilitiesAction types and per-rental rate caps for a platform
/v1/platforms/{platform}/nichesValid warming_niche values for opt-in warming
List Platforms
curl https://api.attentionfactory.com/v1/platforms \
-H "Authorization: Bearer af_live_sk_..."{
"platforms": ["instagram", "tiktok", "reddit", "facebook", "x", "linkedin"]
}Platform Capabilities
Returns the action types available on a platform and the rate caps applied per rental. Use this to know which type values are valid inPOST .../actions.
curl https://api.attentionfactory.com/v1/platforms/instagram/capabilities \
-H "Authorization: Bearer af_live_sk_..."Niche Catalog
Opt-in warming pre-primes a rented account for a specific audience over a 7-day pre-activation window. Use one of these values as warming_niche when creating a rental. Unknown values are rejected with a 400 before any credits are charged.
curl https://api.attentionfactory.com/v1/platforms/instagram/niches \
-H "Authorization: Bearer af_live_sk_..."{
"platform": "instagram",
"niches": ["fitness", "food", "tech-reviews", "travel"]
}Rent an Account
Reserve a verified social account for a whole month. Pricing is monthly; actions incur no per-call charges. Every rental is charged upfront; if warming doesn't complete within 14 days the rental auto-refunds.
Endpoints
/v1/rentalsCreate a rental (returns 202)
/v1/rentalsList your rentals (supports ?status=)
/v1/rentals/{id}Get rental detail
/v1/rentals/{id}Update auto_renew (and other mutable fields)
/v1/rentals/{id}Release early or cancel a pending rental
/v1/rentals/{id}/extendExtend an active rental by N months
/v1/rentals/{id}/renewRenew an active or recently-expired rental
Create Rental
curl -X POST https://api.attentionfactory.com/v1/rentals \
-H "Authorization: Bearer af_live_sk_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: my-rental-001" \
-d '{
"platform": "instagram",
"months": 1,
"auto_renew": true,
"warming_niche": "tech-reviews",
"branding": {
"bio": "Builder. Coffee. Code.",
"display_name": "Launchpad"
}
}'Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| platform | string | Yes | One of: instagram, tiktok, reddit, facebook, x, linkedin |
| months | integer | No | 1–12. Defaults to 1 |
| auto_renew | bool | No | Auto-renew when the rental window closes. Defaults to true |
| warming_niche | string | No | Opt in to 7-day pre-warming on this niche. Must be in the platform's niche catalog |
| branding | object | No | Branding preset applied automatically on activation |
The branding object accepts any subset ofbio,display_name,avatar_url,banner_url, andusername. Each field is applied as a queued action the moment the rental activates.
Rental Status Values
| Status | Meaning |
|---|---|
| warming | Pre-activation. The account is being prepared and actions cannot be submitted yet. expires_pending_at indicates when the rental auto-refunds if warming doesn't complete |
| active | Rental is live. Submit actions against the rental |
| expired | Rental window closed naturally (auto-renew disabled or failed) |
| refunded | Credits returned. Warming did not complete within the 14-day guarantee window |
| released | Customer released the rental early. No refund (month-committal) |
| cancelled | Customer cancelled while still pre-activation. Credits refunded |
Extend / Renew
curl -X POST https://api.attentionfactory.com/v1/rentals/$RENTAL_ID/extend \
-H "Authorization: Bearer af_live_sk_..." \
-H "Content-Type: application/json" \
-d '{"months": 2}'POST /renew has the same body shape. Use it to re-start a recently expired rental on the same account (same anonymized id).
Toggle Auto-Renew
PATCH /v1/rentals/{id} updates mutable rental fields. Today the only customer-controllable field is auto_renew; flip it any time before the rental window closes. Returns the updated rental.
curl -X PATCH https://api.attentionfactory.com/v1/rentals/$RENTAL_ID \
-H "Authorization: Bearer af_live_sk_..." \
-H "Content-Type: application/json" \
-d '{"auto_renew": false}'Brand an Account
Change your rented account's bio, display name, avatar, banner, and username in one request. The server fans out to one queued action per field you provide. Rate caps and review modes apply per sub-action.
Endpoint
/v1/rentals/{id}/brandingApply bio / display name / avatar / banner / username in one batch
Field support differs by platform — the sample below changes as you switch platforms. Fields not supported on the selected platform are simply omitted from the example.
Platform
curl -X POST https://api.attentionfactory.com/v1/rentals/$RENTAL_ID/branding \
-H "Authorization: Bearer af_live_sk_..." \
-H "Content-Type: application/json" \
-d '{
"bio": "Builder. Coffee. Code.",
"display_name": "Launchpad",
"avatar_url": "https://cdn.example.com/avatar.jpg",
"username": "launchpad_labs",
"pronouns": "she/her",
"category": "Artist"
}'{
"rental_id": "4e1a5c98-1d23-4c9e-b3a7-0fdbc2a6e1b3",
"platform": "instagram",
"mode": "applied",
"results": [
{"field": "bio", "action_type": "branding.bio", "action_id": "9ab72c01-...", "status": "queued"},
{"field": "display_name", "action_type": "branding.display_name", "action_id": "f2c91e45-...", "status": "queued"}
],
"preset": null
}If the rental is still warming, the request returnsmode: "preset_stored" instead — the batch is saved and applied automatically when the rental activates. Re-posting while pending REPLACES the previously stored preset. At least one field must be non-null (empty bodies return 400).
Warm an Account
Enroll your rented account in a warming schedule — the app gradually builds authentic engagement over the duration you pick. You can pre-warm at rental creation via the warming_niche field, or enroll post-creation via this endpoint.
Endpoints
/v1/rentals/{id}/warmingEnroll the rental in a warming schedule
/v1/rentals/{id}/warmingCancel a pending warming enrolment
Request Body
| Field | Type | Default | Description |
|---|---|---|---|
| niche | string | — | Optional, max 50 chars. See GET /v1/platforms/{platform}/niches for the platform's catalog. Pace and duration are managed server-side |
Enroll
curl -X POST https://api.attentionfactory.com/v1/rentals/$RENTAL_ID/warming \
-H "Authorization: Bearer af_live_sk_..." \
-H "Content-Type: application/json" \
-d '{"niche": "tech-reviews"}'{
"rental_id": "4e1a5c98-1d23-4c9e-b3a7-0fdbc2a6e1b3",
"action_id": "9ab72c01-5d62-4f0b-a8cc-1d4a7b2fc309",
"status": "queued"
}Cancel
curl -X DELETE https://api.attentionfactory.com/v1/rentals/$RENTAL_ID/warming \
-H "Authorization: Bearer af_live_sk_..."Cancels the most recent warming enrolment on the rental if it's still queued. 404 if there's no matching active enrolment.
Submit Actions
Actions are the unit of work performed on a rented account. They run asynchronously on real people's devices: the request returns 202 Accepted with a queued status, and the final state arrives via webhook or poll.
Endpoints
/v1/rentals/{rental_id}/{platform}/actionsSubmit a new action
/v1/rentals/{rental_id}/actionsList actions on a rental (supports ?status=)
/v1/rentals/{rental_id}/actions/{action_id}Get action detail
/v1/rentals/{rental_id}/actions/{action_id}Cancel a still-queued action
/v1/rentals/{rental_id}/actions/{action_id}/analyticsPost-level analytics for post-type actions
Submit Action
The URL carries both the rental and platform; the body carries the actiontype and typedparams. Supply anIdempotency-Key header for retries — submitting twice with the same key returns the existing action instead of creating a duplicate. Availability varies by platform; pick a platform and an action below to see the exact request and response. Rate limits also vary per platform and action — call GET /v1/platforms/{platform}/capabilities for the definitive live list with caps.
Platform
Action
Publish a single image with optional caption. Supported on Instagram, Facebook, X, LinkedIn. All TikTok/IG composition options from the shared PostOptionsMixin apply: sound_name, location, link_url, allow_comments, allow_duet, allow_stitch, ai_generated, allow_visual_search, audience_control. LinkedIn composer options also accepted (ignored on other platforms): `visibility` (anyone / connections_only / group), `group_url` (required when visibility="group"; must be an https://linkedin.com/... URL), `comment_control` (anyone / connections_only / no_one), `brand_partner_url` (LinkedIn company URL — presence enables the Paid Partnership label). Include only the fields you want to set — omit the rest to keep the platform default.
curl -X POST https://api.attentionfactory.com/v1/rentals/$RENTAL_ID/instagram/actions \
-H "Authorization: Bearer af_live_sk_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: my-action-001" \
-d '{
"type": "post.image",
"params": {
"media_url": "https://cdn.example.com/hero.jpg",
"caption": "Launching today.",
"location": "San Francisco, CA",
"allow_comments": true,
"audience_control": "everyone"
}
}'{
"id": "9ab72c01-5d62-4f0b-a8cc-1d4a7b2fc309",
"rental_id": "4e1a5c98-1d23-4c9e-b3a7-0fdbc2a6e1b3",
"platform": "instagram",
"action_type": "post.image",
"status": "queued",
"created_at": "2026-04-19T12:05:00Z"
}Action Status Values
| Status | Meaning |
|---|---|
| queued | Accepted and awaiting a provider |
| assigned | Provider picked up the action |
| in_progress | Provider is working |
| submitted | Provider submitted proof; awaiting verification |
| verified | Terminal: action completed successfully |
| failed | Terminal: action failed or was rejected on review |
action.* webhooks andGET /v1/rentals/{id}/actions — wait forverified or failed.Analytics
Read account-level and post-level metrics.
Endpoints
/v1/rentals/{id}/analyticsAccount-level analytics from the upstream provider (active rentals only)
/v1/rentals/{id}/actions/{action_id}/analyticsPost-level analytics for a single post-type action
/v1/rentals/{id}/capabilitiesAction types available for this rental's platform
Account Analytics
GET /v1/rentals/{id}/analytics returns the latest account-level metrics (followers, following, post count, engagement) from the upstream provider. Only available while the rental isactive; other statuses return 400. Coverage varies per platform — TikTok typically returns every metric, Reddit returns few.
curl https://api.attentionfactory.com/v1/rentals/$RENTAL_ID/analytics \
-H "Authorization: Bearer af_live_sk_..."Post Analytics
Post-type actions expose upstream post-level analytics (views, likes, comments). Non-post action types return 400. Newly-verified posts may take a few seconds before analytics are populated — retry on 400 with "not yet available".
curl https://api.attentionfactory.com/v1/rentals/$RENTAL_ID/actions/$ACTION_ID/analytics \
-H "Authorization: Bearer af_live_sk_..."Profile
GET /v1/rentals/{id} includes a live profile object on active rentals: username,display_name,avatar_url, and follower / following / post counts. Count fields report null if the platform doesn't supply them. The profile object itself is nullbefore activation, on terminal statuses, and on transient fetch failure — the rental itself never fails because the profile fetch did. Not returned on GET /v1/rentals (list); fetch each rental individually for profile data.
Capabilities
GET /v1/rentals/{id}/capabilities is a convenience for your UI — same shape as GET /v1/platforms/{platform}/capabilities, scoped to the rental's platform. Lets you check "what can I do with this rental right now" without mapping rental → platform yourself.
Billing
Track your credit balance and transaction history. Rentals are charged upfront at the monthly rate for each whole month requested.
Endpoints
/v1/billing/balanceGet current credit balance
/v1/billing/transactionsList transaction history
Balance
curl https://api.attentionfactory.com/v1/billing/balance \
-H "Authorization: Bearer af_live_sk_..."Transactions
curl https://api.attentionfactory.com/v1/billing/transactions \
-H "Authorization: Bearer af_live_sk_..."Webhooks
Register HTTPS endpoints to receive real-time notifications when rentals activate, actions progress, or credits move. Deliveries are signed with HMAC-SHA256.
Endpoints
/v1/webhooksRegister a webhook endpoint
/v1/webhooksList registered webhooks
/v1/webhooks/{id}Remove a webhook
/v1/webhooks/{id}/rotate-secretRotate the HMAC signing secret
/v1/webhooks/{id}/deliveriesView delivery log for a webhook
Register Webhook
curl -X POST https://api.attentionfactory.com/v1/webhooks \
-H "Authorization: Bearer af_live_sk_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://acme.com/webhooks/af",
"events": ["rental.active", "action.verified", "action.failed"],
"secret": "whsec_your_signing_secret"
}'Event Types
Every delivery wraps the event data in an envelope containing the event name, a timestamp, and the event-specificdata object.
Rental events
| Event | When it fires |
|---|---|
| rental.active | Rental transitions from warming to active and can accept actions |
| rental.cancelled | Customer cancelled a still-pending rental; credits refunded |
| rental.refunded | Pending window elapsed or pre-warming could not complete; credits refunded |
| rental.expired | Rental window closed naturally |
Action events
Emitted as action.{status} for each status transition. Subscribe only to the ones you need.
| Event | Meaning |
|---|---|
| action.queued | Action accepted |
| action.assigned | Provider picked it up |
| action.in_progress | Provider started work |
| action.submitted | Proof submitted by provider |
| action.verified | Terminal: succeeded |
| action.failed | Terminal: failed or rejected |
{
"event": "action.verified",
"timestamp": "2026-04-19T12:30:00Z",
"data": {
"action_id": "9ab72c01-5d62-4f0b-a8cc-1d4a7b2fc309",
"rental_id": "4e1a5c98-1d23-4c9e-b3a7-0fdbc2a6e1b3",
"platform": "instagram",
"action_type": "post.image",
"status": "verified"
}
}Signature Verification
Each delivery includes an X-Webhook-Signature header with an HMAC-SHA256 signature of the JSON data field (sorted keys). Verify against your webhook secret before trusting the payload.
const crypto = require('crypto');
function verifyWebhook(dataJson, signatureHeader, secret) {
// signatureHeader looks like: "sha256=<hex>"
const provided = signatureHeader.replace(/^sha256=/, '');
const expected = crypto
.createHmac('sha256', secret)
.update(dataJson)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(provided),
Buffer.from(expected)
);
}action_id /rental_id + event name on your side.Errors
The API uses standard HTTP status codes. All error responses include a detail field with a human-readable message.
Error Response Format
{
"detail": "Insufficient credits. Need 99.00, have 12.00"
}Status Codes
| Code | Meaning | Common Cause |
|---|---|---|
| 400 | Bad Request | Missing or invalid fields (e.g. unknown warming_niche) |
| 401 | Unauthorized | Missing or invalid API key |
| 402 | Payment Required | Insufficient credit balance |
| 403 | Forbidden | Action not allowed for your subscription tier |
| 404 | Not Found | Resource does not exist or not owned by your business |
| 409 | Conflict | Invalid state transition (e.g. extending an expired rental) |
| 422 | Unprocessable Entity | Action params failed schema validation |
| 429 | Too Many Requests | Per-rental rate cap exceeded (see Retry-After header) |
| 500 | Internal Server Error | Something went wrong on our end |