← all adapters

instagram-style

simulates Instagram Graph API v21.0

restadapter v0.1.010 routes

verification

VMVM tier — no SDK suite yet· surface 10 · not implemented 4 · differs 5

use it

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

# then
$ stunt up

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

how to mock the Instagram Graph API locally

Install stunt, paste the service block above into stunt.yaml, run stunt up — then point your client at localhost instead of Instagram Graph API. 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 Instagram Graph API v21.0 surface — the data is fake, the behavior is real.

backing stores

tokenscodescontainersmedia

api surface (10)

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

10 routes
GET/oauth/authorize
POST/oauth/access_token
GET/v21.0/me
GET/v21.0/refresh_access_token
GET/v21.0/{container_id}
GET/v21.0/{media_id}/comments
GET/v21.0/{media_id}/insights
POST/v21.0/{ig_user_id}/media_publish
POST/v21.0/{ig_user_id}/media
GET/v21.0/{ig_user_id}/media

VM-verified behaviors (44)

  • 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 bound to a fresh IG user
  • the code is single-use: a replay is invalid_grant
  • client mismatches are 400 invalid_client
  • a mismatched attempt must not burn the code
  • 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 OAuth-bound profile
  • media_count starts at 0 and tracks published media
  • a second user's profile counts only its own media
  • a container without image_url or video_url is a code-100 400
  • create assigns a c_* container id
  • a fresh container polls IN_PROGRESS and publish is gated
  • the status derives FINISHED after the ~3s window
  • publishing a FINISHED container assigns an m_* media id
  • simulate_fail ends in ERROR and never publishes
  • unknown container ids answer the catch-all 404
  • a video container publishes VIDEO media carrying the video url
  • the media edge lists newest first (reverse chronological)
  • ?fields= projects each row and drops unknown fields
  • limit pages through after cursors with a next that keeps the query
  • a malformed after cursor is a code-100 400
  • the list is scoped to the path user
  • all four manifest metrics return in canonical order
  • values are deterministic across reads
  • ?metric= filters to the requested names
  • an unknown metric name empties the data set (deviation, as-is)
  • insights for an unknown media id are the catch-all 404
  • comments authorize via the access_token query param
  • the bearer header authorizes the identical read
  • a bad query token is the 190 envelope
  • since hides comments at-or-before the cutoff
  • comments on an unknown media id are a code-100 OAuthException 404
  • refresh demands a token (query param or bearer)
  • an unknown token is rejected with 190
  • refresh mints a fresh 60-day token; the old one keeps working
  • the refreshed token outlives the original's expiry

Not implemented (4)

  • No account-level insights (GET /{ig_user_id}/insights), per-media only
  • No stories publishing (media_type=STORIES) or story insights
  • No hashtag search (ig_hashtag_search, top_media, recent_media)
  • No comment replies, delete, hide, or moderation endpoints

Differs from the real API (5)

  • Container processing fixed at ~3s IN_PROGRESS before FINISHED or ERROR
  • simulate_fail=true create flag forces container ERROR; real API has no such switch
  • Cursors are forward-only plain offsets; no before cursor or paging.previous
  • An unknown insights metric returns 200 with empty data; real Graph answers error code 100
  • media_publish does not check container ownership across users
want more of the Instagram Graph API 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.