← 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.