← all adapters

threads-style

simulates Threads API (Meta) v1.0

restadapter v0.1.08 routes

verification

VMVM tier — no SDK suite yet· surface 8 · not implemented 3 · differs 6

use it

# add to stunt.yaml
services:
  threads:
    adapter: embedded:threads-style

# then
$ stunt up

The embedded: source extracts this adapter from the binary — no git clone, fully offline.

how to mock the Threads API (Meta) API locally

Install stunt, paste the service block above into stunt.yaml, run stunt up — then point your client at localhost instead of Threads API (Meta). It works offline, keeps state across requests and restarts, and every response is synthetic: the route shapes, status codes, pagination, and webhook delivery follow the real Threads API (Meta) v1.0 surface — the data is fake, the behavior is real.

backing stores

tokenscodescontainersmedia

api surface (8)

generated from the adapter manifest — exactly what boots, nothing more

8 routes
GET/oauth/authorize
POST/oauth/access_token
GET/v1.0/me
GET/v1.0/{container_id}
GET/v1.0/{id}/insights
POST/v1.0/{id}/threads_publish
POST/v1.0/{id}/threads
GET/v1.0/{id}/threads

VM-verified behaviors (39)

  • authorize without redirect_uri, state or client_id is invalid_request
  • authorize redirects back with a fresh code and the state echoed
  • a redirect_uri that already carries a query is joined with &
  • the exchange demands grant_type=authorization_code
  • an unknown code is 400 invalid_grant
  • a good exchange mints a token, user and refresh token
  • the code is single-use: a replay is invalid_grant
  • client mismatches are 400 invalid_client
  • a mismatched attempt leaves the code redeemable (house rule)
  • a second flow mints a distinct user
  • a missing bearer is 401 in the Graph error envelope
  • wrong schemes and unknown bearers answer the same 190
  • every API route enforces the same gate
  • a bearer dies at its clock-derived 60-day expiry
  • me returns the static mock profile
  • every user's token sees the same static profile (deviation, as-is)
  • ?fields= is ignored: the full profile always comes back
  • a container without media_type=TEXT and text is a code-100 400
  • create assigns a c_* container id
  • a TEXT container polls finished immediately (no processing window)
  • back-to-back publish assigns an m_* media id
  • republishing the same container mints a second media (deviation, as-is)
  • simulate_fail ends in error and never publishes
  • unknown container ids answer the catch-all 404
  • the inbox lists the user's media newest first
  • each post carries one synthetic reply child
  • the inbox is scoped to the path user
  • ?fields= projection is ignored (deviation, as-is)
  • all four manifest metrics return in canonical order
  • values are deterministic across reads
  • ?metric= projects to the requested names in canonical order
  • an unknown metric name empties the data set (deviation, as-is)
  • insights for an unknown media id are the catch-all 404
  • refresh demands a known refresh_token
  • a refresh mints a fresh 60-day token bound to the same user
  • the response omits the rotated refresh_token (deviation, as-is)
  • the used refresh token is single-use: a replay is invalid_grant
  • the original access token keeps its own 60-day life
  • the refreshed token outlives the original's expiry

Not implemented (3)

  • Only TEXT media containers; no image or video media types or uploads
  • No reply or quote-post creation; inbox replies are synthetic
  • No user-level insights; only 4 per-media metrics

Differs from the real API (6)

  • Container processing is a fixed ~3s clock-derived window; text needs no real poll
  • simulate_fail=true on container create is a simulator-only failure switch
  • Refresh-grant response omits the rotated refresh_token; only the code exchange returns one
  • /me is a static profile shared by every token; the path user is never validated against the bearer
  • The refresh response omits the rotated refresh_token, so each token refreshes only once
  • Republishing a container mints duplicate media
want more of the Threads API (Meta) surface? adapters are YAML + Starlark — the authoring guide covers adding routes, fixtures, and state machines. Open an issue for anything big first, or just file a PR — merged routes ship in the next release.