# Nothing Works Until Meta Says So: Instagram API Setup

> Getting permission to publish to Instagram via the Graph API: the professional account requirement, the Meta developer app, the tester invite step every tutorial skips, the two auth paths, and the 60-day token.

By Vishwajeet Raj · 2026-07-22 · https://vishwajeet.co/blog/instagram-api-setup

---

I built [a small CLI that posts images to Instagram from a folder on my
Mac](/blog/posting-to-instagram-from-my-terminal). Writing the script took an
evening. Getting permission to call the API took longer, and it's the part
every tutorial waves through, so here it is in full.

The goal is two values: an `IG_ACCESS_TOKEN` (a long-lived Instagram API
token) and an `IG_USER_ID` (your account's numeric ID). Everything below is
the path to those.

## Your account must be Professional

Personal Instagram accounts can't publish through the API at all. Instagram
app, Settings, Account type and tools, Switch to professional account.
Business or Creator, both work.

## You need a Meta developer app

Even though you're not shipping an app. Go to developers.facebook.com, My
Apps, Create App, use case **Other**, type **Business**.

The Facebook account that owns this app does *not* need to be linked to your
Instagram account or share an email with it. It just owns the app. The
Instagram account gets connected separately by logging in with its own
credentials. That confused me for an hour.

## You have to invite yourself, then accept

The app sits in Development Mode, and a Development Mode app can only touch
accounts that hold a role on it. So you add your own Instagram account as an
**Instagram Tester** under App roles, Roles. Then comes the step that's easy
to miss: go into Instagram itself, Edit Profile, Apps and Websites, **Tester
Invites**, and accept. Until you accept, the account shows as pending on the
dashboard and token generation doesn't work.

The upside of this arrangement is that the app can stay in Development Mode
forever. It only ever touches my own account, so it never needs App Review.

## Two auth paths, and they don't mix

Nothing on the dashboard tells you these are different products:

- **Instagram API with Instagram Login**. Add the Instagram product to your
  app, choose "API setup with Instagram business login", add your account, grant
  `instagram_business_basic` and `instagram_business_content_publish`, generate
  the token. No Facebook Page required. Host is `graph.instagram.com`.
- **Facebook Login for Business**. The older path. Requires a Facebook Page
  actually linked to your Instagram account, and you dig the user ID out via
  `GET /me/accounts`, then `GET /{page-id}?fields=instagram_business_account`.
  Host is `graph.facebook.com`.

Most tutorials cover the older Facebook Login path, so that's what you'll
find when you search. I went with Instagram Login
and it was less hassle: no Facebook Page needed, and getting the user ID is a
single request.

## Generating the access token

On the app dashboard, open the Instagram product and find **API setup with
Instagram business login**. Under "Generate access tokens", click **Add
account** and log in with your Instagram account (this only works after the
tester invite is accepted). Grant at least these two permissions:

- `instagram_business_basic`
- `instagram_business_content_publish`

Then click **Generate token** next to your account and copy it. This is the
long-lived token, and it's your `IG_ACCESS_TOKEN`. You don't have to build an
OAuth flow for a personal script. The dashboard button is the whole thing.

## Finding your user ID

It's not shown in the dashboard. You ask for it:

```bash
curl "https://graph.instagram.com/v23.0/me?fields=user_id,username&access_token=YOUR_TOKEN"
```

The response contains two IDs. `user_id` is the professional-account ID that
every publishing call is scoped to. `id` is
app-scoped and will fail with a permissions error that doesn't mention IDs at
all. Copy the `user_id`.

## The token expires in about 60 days

There's a refresh endpoint, a plain GET that hands back a fresh 60-day token:

```bash
curl "https://graph.instagram.com/refresh_access_token?grant_type=ig_refresh_token&access_token=YOUR_CURRENT_TOKEN"
```

Right now I paste the result into `.env` by hand, which is a time bomb I've
scheduled for myself roughly every two months.

## One last trap: location IDs

A location tag on a post is a *Facebook Page* ID, and looking one up through
the Pages Search API needs a Facebook Login token, not the Instagram one you
just spent an hour getting. I gave up and pulled the numeric ID straight out
of a Facebook place page URL.

---

With the token and user ID in hand, actually publishing is its own story:
containers, polling, image constraints, and a Node bug that had nothing to do
with Instagram. That's [the next
post](/blog/posting-to-instagram-from-my-terminal).
