> For the complete documentation index, see [llms.txt](https://docs.pullbay.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.pullbay.com/documentation/api-and-references/instagram.md).

# Instagram

The Pullbay Instagram API provides programmatic access to public Instagram profile, post, reel, story, and comment data. Resolve handles to user IDs, pull a profile, list a user's posts/tagged posts/reels, read active stories, fetch a single post by shortcode, or pull comments on a post — all without scraping or owning an Instagram account of your own.

**Base URL:** `https://dashboard.pullbay.com/api`

## Overview

The Instagram service lets you:

* Resolve a handle (`@username`) to Instagram's internal numeric user ID
* Look up a full user profile by handle or by numeric ID
* List a user's posts, posts they're tagged in, and reels (cursor-paginated)
* Fetch a user's currently-active stories
* Fetch a single post by its shortcode (the code in an `instagram.com/p/{code}/` URL)
* Fetch comments on a post by the post's internal ID (cursor-paginated)

All endpoints are read-only `GET` requests against public Instagram data — no account of your own is required. This service uses **three distinct identifier types that are not interchangeable**: `handle` (the `@username`, passed without the `@`), `id` (Instagram's internal numeric ID for a user, post, or comment), and `code` (a post's shortcode, the segment after `/p/` in a post URL). Always check which one a given endpoint expects.

## Common Use Cases

**Influencer Vetting** — Pull a creator's profile (follower count, post count, verification status) before negotiating a sponsorship, and check their recent posts for content fit and engagement levels.

**Engagement Tracking** — Poll a brand or creator account's posts and reels on a schedule to track `likeCount` and `commentCount` trends over time.

**Campaign Monitoring** — Fetch posts a brand account is tagged in to see how a hashtag or partnership campaign is performing across other accounts.

**Comment Sentiment Analysis** — Pull comments on a post and feed the `message` field into your own sentiment or moderation pipeline.

**Story Archiving** — Capture a user's active stories before they expire (24 hours after posting) for compliance, reporting, or content-repurposing workflows.

## Endpoints

| Endpoint                                | Description                           | Pagination        |
| --------------------------------------- | ------------------------------------- | ----------------- |
| `GET /instagram/userid/{handle}`        | Resolve a handle to a numeric user ID | —                 |
| `GET /instagram/user/handle/{handle}`   | Get a user profile by handle          | —                 |
| `GET /instagram/user/{id}`              | Get a user profile by numeric ID      | —                 |
| `GET /instagram/user/{id}/posts`        | Get posts published by a user         | Cursor / maxItems |
| `GET /instagram/user/{id}/posts/tagged` | Get posts a user is tagged in         | Cursor / maxItems |
| `GET /instagram/user/{id}/reels`        | Get reels published by a user         | Cursor / maxItems |
| `GET /instagram/user/{id}/stories`      | Get a user's currently-active stories | —                 |
| `GET /instagram/post/code/{code}`       | Get a single post by shortcode        | —                 |
| `GET /instagram/post/{id}/comments`     | Get comments on a post                | Cursor / maxItems |

***

### Resolve User ID

Returns whether a handle is available and, if it exists, the resolved Instagram user ID.

**Request**

```http
GET /instagram/userid/{handle}
Authorization: Bearer YOUR_API_KEY
```

**Parameters**

| Parameter | Type          | Required | Default | Description                                                        |
| --------- | ------------- | -------- | ------- | ------------------------------------------------------------------ |
| `handle`  | string (path) | Yes      | —       | Instagram handle, without `@`, 1–100 characters (e.g. `instagram`) |

**Example**

```bash
curl -G "https://dashboard.pullbay.com/api/instagram/userid/instagram" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response**

```json
{
  "status": 200,
  "message": "OK",
  "success": true,
  "data": [
    {
      "isAvailable": true,
      "handle": "instagram",
      "id": "25025320"
    }
  ],
  "pricing": { "creditsCharged": 1 }
}
```

**Response Schema**

| Field                    | Type   | Description                                                               |
| ------------------------ | ------ | ------------------------------------------------------------------------- |
| `data`                   | array  | Array containing a single [User ID lookup object](#user-id-lookup-object) |
| `pricing.creditsCharged` | number | Credits charged for this request                                          |

**Credit cost:** charged dynamically per request; the exact amount is always returned in `pricing.creditsCharged`. No published flat rate — read the figure from the response.

***

### Get User By Handle

Returns an Instagram user profile by handle (without `@`).

**Request**

```http
GET /instagram/user/handle/{handle}
Authorization: Bearer YOUR_API_KEY
```

**Parameters**

| Parameter | Type          | Required | Default | Description                                                        |
| --------- | ------------- | -------- | ------- | ------------------------------------------------------------------ |
| `handle`  | string (path) | Yes      | —       | Instagram handle, without `@`, 1–100 characters (e.g. `instagram`) |

**Example**

```bash
curl -G "https://dashboard.pullbay.com/api/instagram/user/handle/instagram" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response**

```json
{
  "status": 200,
  "message": "OK",
  "success": true,
  "data": [
    {
      "type": "user",
      "isAvailable": true,
      "id": "25025320",
      "username": "instagram",
      "fullName": "Instagram",
      "biography": "Discover what's new on Instagram 🔎✨",
      "profilePicUrl": "https://instagram.com/static/images/profile.jpg",
      "website": "https://about.instagram.com",
      "category": "App page",
      "cityName": null,
      "isPrivate": false,
      "isVerified": true,
      "isBusiness": true,
      "hasVideos": true,
      "hasGuides": false,
      "postCount": 8200,
      "followerCount": 689000000,
      "followingCount": 264,
      "totalReelsCount": 1850,
      "bioLinks": []
    }
  ],
  "pricing": { "creditsCharged": 1 }
}
```

**Response Schema**

| Field                    | Type   | Description                                           |
| ------------------------ | ------ | ----------------------------------------------------- |
| `data`                   | array  | Array containing a single [User object](#user-object) |
| `pricing.creditsCharged` | number | Credits charged for this request                      |

**Credit cost:** dynamic, returned in `pricing.creditsCharged`. No published flat rate.

***

### Get User By ID

Returns an Instagram user profile by numeric user ID.

**Request**

```http
GET /instagram/user/{id}
Authorization: Bearer YOUR_API_KEY
```

**Parameters**

| Parameter | Type          | Required | Default | Description                                                   |
| --------- | ------------- | -------- | ------- | ------------------------------------------------------------- |
| `id`      | string (path) | Yes      | —       | Numeric Instagram user ID, 1–100 characters (e.g. `25025320`) |

**Example**

```bash
curl -G "https://dashboard.pullbay.com/api/instagram/user/25025320" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response**

```json
{
  "status": 200,
  "message": "OK",
  "success": true,
  "data": [
    {
      "type": "user",
      "isAvailable": true,
      "id": "25025320",
      "username": "instagram",
      "fullName": "Instagram",
      "biography": "Discover what's new on Instagram 🔎✨",
      "profilePicUrl": "https://instagram.com/static/images/profile.jpg",
      "website": "https://about.instagram.com",
      "category": "App page",
      "cityName": null,
      "isPrivate": false,
      "isVerified": true,
      "isBusiness": true,
      "hasVideos": true,
      "hasGuides": false,
      "postCount": 8200,
      "followerCount": 689000000,
      "followingCount": 264,
      "totalReelsCount": 1850,
      "bioLinks": []
    }
  ],
  "pricing": { "creditsCharged": 1 }
}
```

**Response Schema**

| Field                    | Type   | Description                                           |
| ------------------------ | ------ | ----------------------------------------------------- |
| `data`                   | array  | Array containing a single [User object](#user-object) |
| `pricing.creditsCharged` | number | Credits charged for this request                      |

**Credit cost:** dynamic, returned in `pricing.creditsCharged`. No published flat rate.

***

### Get User Posts

Returns posts published by an Instagram user. Use `cursor` to paginate or `maxItems` for a one-shot bulk pull (mutually exclusive).

**Request**

```http
GET /instagram/user/{id}/posts
Authorization: Bearer YOUR_API_KEY
```

**Parameters**

| Parameter  | Type            | Required | Default | Description                                                                    |
| ---------- | --------------- | -------- | ------- | ------------------------------------------------------------------------------ |
| `id`       | string (path)   | Yes      | —       | Numeric Instagram user ID, 1–100 characters                                    |
| `maxItems` | integer (query) | No       | —       | One-shot bulk pull, 1–200 results. Mutually exclusive with `cursor`            |
| `cursor`   | string (query)  | No       | —       | Pagination cursor from a previous response. Mutually exclusive with `maxItems` |

**Example**

```bash
curl -G "https://dashboard.pullbay.com/api/instagram/user/25025320/posts" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d maxItems=50
```

**Response**

```json
{
  "status": 200,
  "message": "OK",
  "success": true,
  "data": [
    {
      "type": "photo",
      "id": "3881985252256633854",
      "code": "CzABCdef123",
      "url": "https://www.instagram.com/p/CzABCdef123/",
      "caption": "Check out our latest update!",
      "createdAt": 1714560000,
      "likeCount": 12500,
      "commentCount": 320,
      "isAvailable": true,
      "isCarousel": false,
      "isVideo": false,
      "isPinned": false,
      "isPaidPartnership": false,
      "isLikeAndViewCountsDisabled": false,
      "owner": {
        "id": "25025320",
        "username": "instagram",
        "fullName": "Instagram",
        "profilePicUrl": "https://instagram.com/static/images/profile.jpg",
        "isVerified": true,
        "isPrivate": false
      },
      "coowners": [],
      "location": null,
      "image": {},
      "video": null,
      "audio": null,
      "carouselMedia": []
    }
  ],
  "pagination": { "page": null, "hasNextPage": true, "cursor": "QVFE...", "offset": null },
  "pricing": { "creditsCharged": 1 }
}
```

**Response Schema**

| Field                                   | Type              | Description                                    |
| --------------------------------------- | ----------------- | ---------------------------------------------- |
| `data`                                  | array             | Array of [Post objects](#post-object)          |
| `pagination.hasNextPage`                | boolean, nullable | Whether another page is available              |
| `pagination.cursor`                     | string, nullable  | Cursor to pass as `cursor` on the next request |
| `pagination.page` / `pagination.offset` | nullable          | Unused by this endpoint — always `null` here   |
| `pricing.creditsCharged`                | number            | Credits charged for this request               |

**Credit cost:** dynamic, returned in `pricing.creditsCharged`. No published flat rate — read the figure from each response.

***

### Get User Tagged Posts

Returns posts where the Instagram user is tagged. Use `cursor` to paginate or `maxItems` for a one-shot bulk pull (mutually exclusive).

**Request**

```http
GET /instagram/user/{id}/posts/tagged
Authorization: Bearer YOUR_API_KEY
```

**Parameters**

| Parameter  | Type            | Required | Default | Description                                                                    |
| ---------- | --------------- | -------- | ------- | ------------------------------------------------------------------------------ |
| `id`       | string (path)   | Yes      | —       | Numeric Instagram user ID, 1–100 characters                                    |
| `maxItems` | integer (query) | No       | —       | One-shot bulk pull, 1–200 results. Mutually exclusive with `cursor`            |
| `cursor`   | string (query)  | No       | —       | Pagination cursor from a previous response. Mutually exclusive with `maxItems` |

**Example**

```bash
curl -G "https://dashboard.pullbay.com/api/instagram/user/25025320/posts/tagged" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d cursor="QVFE..."
```

**Response**

```json
{
  "status": 200,
  "message": "OK",
  "success": true,
  "data": [
    {
      "type": "photo",
      "id": "3881985252256633900",
      "code": "CzXYZdef456",
      "url": "https://www.instagram.com/p/CzXYZdef456/",
      "caption": "Great day at the launch event!",
      "createdAt": 1714646400,
      "likeCount": 4300,
      "commentCount": 95,
      "isAvailable": true,
      "isCarousel": false,
      "isVideo": false,
      "isPinned": false,
      "isPaidPartnership": false,
      "isLikeAndViewCountsDisabled": false,
      "owner": {
        "id": "7894561230",
        "username": "anotheruser",
        "fullName": "Another User",
        "profilePicUrl": "https://instagram.com/static/images/profile2.jpg",
        "isVerified": false,
        "isPrivate": false
      },
      "coowners": [],
      "location": null,
      "image": {},
      "video": null,
      "audio": null,
      "carouselMedia": []
    }
  ],
  "pagination": { "page": null, "hasNextPage": true, "cursor": "QVFE...", "offset": null },
  "pricing": { "creditsCharged": 1 }
}
```

**Response Schema**

| Field                                   | Type              | Description                                    |
| --------------------------------------- | ----------------- | ---------------------------------------------- |
| `data`                                  | array             | Array of [Post objects](#post-object)          |
| `pagination.hasNextPage`                | boolean, nullable | Whether another page is available              |
| `pagination.cursor`                     | string, nullable  | Cursor to pass as `cursor` on the next request |
| `pagination.page` / `pagination.offset` | nullable          | Unused by this endpoint — always `null` here   |
| `pricing.creditsCharged`                | number            | Credits charged for this request               |

**Credit cost:** dynamic, returned in `pricing.creditsCharged`. No published flat rate.

***

### Get User Reels

Returns reels published by an Instagram user. Use `cursor` to paginate or `maxItems` for a one-shot bulk pull (mutually exclusive). Reels are returned using the same [Post object](#post-object) schema as the posts endpoints — there is no separate "reel" schema.

**Request**

```http
GET /instagram/user/{id}/reels
Authorization: Bearer YOUR_API_KEY
```

**Parameters**

| Parameter  | Type            | Required | Default | Description                                                                    |
| ---------- | --------------- | -------- | ------- | ------------------------------------------------------------------------------ |
| `id`       | string (path)   | Yes      | —       | Numeric Instagram user ID, 1–100 characters                                    |
| `maxItems` | integer (query) | No       | —       | One-shot bulk pull, 1–200 results. Mutually exclusive with `cursor`            |
| `cursor`   | string (query)  | No       | —       | Pagination cursor from a previous response. Mutually exclusive with `maxItems` |

**Example**

```bash
curl -G "https://dashboard.pullbay.com/api/instagram/user/25025320/reels" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d maxItems=25
```

**Response**

```json
{
  "status": 200,
  "message": "OK",
  "success": true,
  "data": [
    {
      "type": "reel",
      "id": "3881985252256634000",
      "code": "CzREELabc789",
      "url": "https://www.instagram.com/p/CzREELabc789/",
      "caption": "New reel just dropped 🎥",
      "createdAt": 1714732800,
      "likeCount": 98000,
      "commentCount": 1820,
      "isAvailable": true,
      "isCarousel": false,
      "isVideo": true,
      "isPinned": false,
      "isPaidPartnership": false,
      "isLikeAndViewCountsDisabled": false,
      "owner": {
        "id": "25025320",
        "username": "instagram",
        "fullName": "Instagram",
        "profilePicUrl": "https://instagram.com/static/images/profile.jpg",
        "isVerified": true,
        "isPrivate": false
      },
      "coowners": [],
      "location": null,
      "image": null,
      "video": {},
      "audio": {},
      "carouselMedia": []
    }
  ],
  "pagination": { "page": null, "hasNextPage": true, "cursor": "QVFE...", "offset": null },
  "pricing": { "creditsCharged": 1 }
}
```

**Response Schema**

| Field                                   | Type              | Description                                                          |
| --------------------------------------- | ----------------- | -------------------------------------------------------------------- |
| `data`                                  | array             | Array of [Post objects](#post-object) (returned with `type: "reel"`) |
| `pagination.hasNextPage`                | boolean, nullable | Whether another page is available                                    |
| `pagination.cursor`                     | string, nullable  | Cursor to pass as `cursor` on the next request                       |
| `pagination.page` / `pagination.offset` | nullable          | Unused by this endpoint — always `null` here                         |
| `pricing.creditsCharged`                | number            | Credits charged for this request                                     |

**Credit cost:** dynamic, returned in `pricing.creditsCharged`. No published flat rate.

***

### Get User Stories

Returns the user's currently-active Instagram stories. Not paginated — stories expire 24 hours after posting, so the full active set is always returned in one call.

**Request**

```http
GET /instagram/user/{id}/stories
Authorization: Bearer YOUR_API_KEY
```

**Parameters**

| Parameter | Type          | Required | Default | Description                                 |
| --------- | ------------- | -------- | ------- | ------------------------------------------- |
| `id`      | string (path) | Yes      | —       | Numeric Instagram user ID, 1–100 characters |

**Example**

```bash
curl -G "https://dashboard.pullbay.com/api/instagram/user/25025320/stories" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response**

```json
{
  "status": 200,
  "message": "OK",
  "success": true,
  "data": [
    {
      "type": "video",
      "id": "3245678901234567890",
      "code": "CzABCdef123",
      "createdAt": 1714560000,
      "expiringAt": 1714646400,
      "duration": 14.97,
      "hasAudio": true,
      "hasTranslation": false,
      "canReshare": true,
      "canReply": true,
      "isVideo": true,
      "owner": {
        "id": "25025320",
        "username": "instagram",
        "fullName": "Instagram",
        "profilePicUrl": "https://instagram.com/static/images/profile.jpg",
        "isVerified": true,
        "isPrivate": false
      },
      "coowners": [],
      "image": null,
      "video": {},
      "audio": {},
      "link": null,
      "comments": [],
      "mentions": [],
      "hashtags": []
    }
  ],
  "pricing": { "creditsCharged": 1 }
}
```

**Response Schema**

| Field                    | Type   | Description                             |
| ------------------------ | ------ | --------------------------------------- |
| `data`                   | array  | Array of [Story objects](#story-object) |
| `pricing.creditsCharged` | number | Credits charged for this request        |

**Credit cost:** dynamic, returned in `pricing.creditsCharged`. No published flat rate.

***

### Get Post By Shortcode

Returns a single Instagram post by its shortcode (the segment after `/p/` in the post's URL).

**Request**

```http
GET /instagram/post/code/{code}
Authorization: Bearer YOUR_API_KEY
```

**Parameters**

| Parameter | Type          | Required | Default | Description                                                                                       |
| --------- | ------------- | -------- | ------- | ------------------------------------------------------------------------------------------------- |
| `code`    | string (path) | Yes      | —       | Post shortcode, 1–100 characters (e.g. `CzABCdef123`, the code in `instagram.com/p/CzABCdef123/`) |

**Example**

```bash
curl -G "https://dashboard.pullbay.com/api/instagram/post/code/CzABCdef123" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response**

```json
{
  "status": 200,
  "message": "OK",
  "success": true,
  "data": [
    {
      "type": "photo",
      "id": "3881985252256633854",
      "code": "CzABCdef123",
      "url": "https://www.instagram.com/p/CzABCdef123/",
      "caption": "Check out our latest update!",
      "createdAt": 1714560000,
      "likeCount": 12500,
      "commentCount": 320,
      "isAvailable": true,
      "isCarousel": false,
      "isVideo": false,
      "isPinned": false,
      "isPaidPartnership": false,
      "isLikeAndViewCountsDisabled": false,
      "owner": {
        "id": "25025320",
        "username": "instagram",
        "fullName": "Instagram",
        "profilePicUrl": "https://instagram.com/static/images/profile.jpg",
        "isVerified": true,
        "isPrivate": false
      },
      "coowners": [],
      "location": null,
      "image": {},
      "video": null,
      "audio": null,
      "carouselMedia": []
    }
  ],
  "pricing": { "creditsCharged": 1 }
}
```

**Response Schema**

| Field                    | Type   | Description                                           |
| ------------------------ | ------ | ----------------------------------------------------- |
| `data`                   | array  | Array containing a single [Post object](#post-object) |
| `pricing.creditsCharged` | number | Credits charged for this request                      |

**Credit cost:** dynamic, returned in `pricing.creditsCharged`. No published flat rate.

***

### Get Post Comments

Returns comments on an Instagram post. Use `cursor` to paginate or `maxItems` for a one-shot bulk pull (mutually exclusive). Takes the post's internal numeric `id`, **not** its shortcode.

**Request**

```http
GET /instagram/post/{id}/comments
Authorization: Bearer YOUR_API_KEY
```

**Parameters**

| Parameter  | Type            | Required | Default | Description                                                                    |
| ---------- | --------------- | -------- | ------- | ------------------------------------------------------------------------------ |
| `id`       | string (path)   | Yes      | —       | Numeric Instagram post ID, 1–100 characters (not the post's shortcode)         |
| `maxItems` | integer (query) | No       | —       | One-shot bulk pull, 1–500 results. Mutually exclusive with `cursor`            |
| `cursor`   | string (query)  | No       | —       | Pagination cursor from a previous response. Mutually exclusive with `maxItems` |

**Example**

```bash
curl -G "https://dashboard.pullbay.com/api/instagram/post/3881985252256633854/comments" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d maxItems=100
```

**Response**

```json
{
  "status": 200,
  "message": "OK",
  "success": true,
  "data": [
    {
      "type": "comment",
      "id": "18470084392099954",
      "userId": "53847071613",
      "message": "Love this!",
      "createdAt": "2026-05-05T19:46:32.000Z",
      "likeCount": 27,
      "replyCount": 0,
      "isRanked": false,
      "user": {
        "id": "53847071613",
        "username": "someuser",
        "fullName": "Some User",
        "profilePicUrl": "https://instagram.com/static/images/profile3.jpg",
        "isPrivate": false,
        "isVerified": false
      }
    }
  ],
  "pagination": { "page": null, "hasNextPage": true, "cursor": "QVFE...", "offset": null },
  "pricing": { "creditsCharged": 1 }
}
```

**Response Schema**

| Field                                   | Type              | Description                                    |
| --------------------------------------- | ----------------- | ---------------------------------------------- |
| `data`                                  | array             | Array of [Comment objects](#comment-object)    |
| `pagination.hasNextPage`                | boolean, nullable | Whether another page is available              |
| `pagination.cursor`                     | string, nullable  | Cursor to pass as `cursor` on the next request |
| `pagination.page` / `pagination.offset` | nullable          | Unused by this endpoint — always `null` here   |
| `pricing.creditsCharged`                | number            | Credits charged for this request               |

**Credit cost:** dynamic, returned in `pricing.creditsCharged`. No published flat rate.

## Errors

All non-2xx responses share the same envelope:

```json
{
  "status": 400,
  "message": "Bad request",
  "success": false,
  "error": { "code": "BAD_REQUEST" }
}
```

| Status | Meaning                                  |
| ------ | ---------------------------------------- |
| `400`  | Bad request — missing/invalid parameters |
| `402`  | Insufficient credits                     |
| `404`  | User, post, or story not found           |

## Object Schema

### User ID lookup object

| Field         | Type    | Description                                                          |
| ------------- | ------- | -------------------------------------------------------------------- |
| `isAvailable` | boolean | Whether the handle exists/is in use                                  |
| `handle`      | string  | The handle that was looked up                                        |
| `id`          | string  | Numeric Instagram user ID. Present only when `isAvailable` is `true` |

### User object

| Field             | Type             | Description                               |
| ----------------- | ---------------- | ----------------------------------------- |
| `type`            | string           | Always `user`                             |
| `isAvailable`     | boolean          | Whether the profile is available          |
| `id`              | string           | Numeric Instagram user ID                 |
| `username`        | string           | Handle, without `@`                       |
| `fullName`        | string           | Display name                              |
| `biography`       | string           | Bio text                                  |
| `profilePicUrl`   | string           | Profile picture URL                       |
| `website`         | string           | Link in bio                               |
| `category`        | string           | Business/category label (e.g. `App page`) |
| `cityName`        | string, nullable | City shown on profile                     |
| `isPrivate`       | boolean          | Whether the account is private            |
| `isVerified`      | boolean          | Whether the account has a verified badge  |
| `isBusiness`      | boolean          | Whether the account is a business account |
| `hasVideos`       | boolean          | Whether the account has published videos  |
| `hasGuides`       | boolean          | Whether the account has published guides  |
| `postCount`       | integer          | Total post count                          |
| `followerCount`   | integer          | Follower count                            |
| `followingCount`  | integer          | Following count                           |
| `totalReelsCount` | integer          | Total reel count                          |
| `bioLinks`        | array            | Links shown in the bio                    |

### Post owner object

Lightweight user reference embedded in posts and stories.

| Field           | Type    | Description                              |
| --------------- | ------- | ---------------------------------------- |
| `id`            | string  | Numeric Instagram user ID                |
| `username`      | string  | Handle, without `@`                      |
| `fullName`      | string  | Display name                             |
| `profilePicUrl` | string  | Profile picture URL                      |
| `isVerified`    | boolean | Whether the account has a verified badge |
| `isPrivate`     | boolean | Whether the account is private           |

### Post object

Used for posts, tagged posts, and reels — reels are returned with `type: "reel"` but share this same schema; there is no separate reel object.

| Field                         | Type             | Description                                                                     |
| ----------------------------- | ---------------- | ------------------------------------------------------------------------------- |
| `type`                        | string           | `photo` / `video` / `carousel` / `reel`                                         |
| `id`                          | string           | Numeric post ID                                                                 |
| `code`                        | string           | Shortcode (the segment after `/p/` in the URL)                                  |
| `url`                         | string           | Permalink to the post                                                           |
| `caption`                     | string           | Caption text                                                                    |
| `createdAt`                   | integer          | Unix timestamp (seconds) the post was published                                 |
| `likeCount`                   | integer          | Like count                                                                      |
| `commentCount`                | integer          | Comment count                                                                   |
| `isAvailable`                 | boolean          | Whether the post is still available                                             |
| `isCarousel`                  | boolean          | Whether the post is a multi-media carousel                                      |
| `isVideo`                     | boolean          | Whether the post is a video                                                     |
| `isPinned`                    | boolean          | Whether the post is pinned to the profile                                       |
| `isPaidPartnership`           | boolean          | Whether the post is a paid partnership                                          |
| `isLikeAndViewCountsDisabled` | boolean          | Whether like/view counts are hidden                                             |
| `owner`                       | object           | [Post owner object](#post-owner-object)                                         |
| `coowners`                    | array            | Additional tagged collaborators, each a [post owner object](#post-owner-object) |
| `location`                    | object, nullable | Tagged location                                                                 |
| `image`                       | object, nullable | Image media data                                                                |
| `video`                       | object, nullable | Video media data                                                                |
| `audio`                       | object, nullable | Audio track data                                                                |
| `carouselMedia`               | array            | Per-slide media for carousel posts                                              |

### Comment object

| Field        | Type               | Description                                                                                    |
| ------------ | ------------------ | ---------------------------------------------------------------------------------------------- |
| `type`       | string             | Always `comment`                                                                               |
| `id`         | string             | Comment ID                                                                                     |
| `userId`     | string             | Numeric ID of the commenter                                                                    |
| `message`    | string             | Comment text                                                                                   |
| `createdAt`  | string (date-time) | When the comment was posted                                                                    |
| `likeCount`  | integer            | Like count                                                                                     |
| `replyCount` | integer            | Reply count                                                                                    |
| `isRanked`   | boolean            | Whether the comment is algorithmically ranked/pinned                                           |
| `user`       | object             | Commenter reference (`id`, `username`, `fullName`, `profilePicUrl`, `isPrivate`, `isVerified`) |

### Story object

| Field            | Type             | Description                                                                     |
| ---------------- | ---------------- | ------------------------------------------------------------------------------- |
| `type`           | string           | `photo` / `video`                                                               |
| `id`             | string           | Story ID                                                                        |
| `code`           | string           | Shortcode                                                                       |
| `createdAt`      | integer          | Unix timestamp (seconds) the story was posted                                   |
| `expiringAt`     | integer          | Unix timestamp (seconds) the story expires                                      |
| `duration`       | number           | Duration in seconds                                                             |
| `hasAudio`       | boolean          | Whether the story has audio                                                     |
| `hasTranslation` | boolean          | Whether translated text is available                                            |
| `canReshare`     | boolean          | Whether the story can be reshared                                               |
| `canReply`       | boolean          | Whether replies are allowed                                                     |
| `isVideo`        | boolean          | Whether the story is a video                                                    |
| `owner`          | object           | [Post owner object](#post-owner-object)                                         |
| `coowners`       | array            | Additional tagged collaborators, each a [post owner object](#post-owner-object) |
| `image`          | object, nullable | Image media data                                                                |
| `video`          | object, nullable | Video media data                                                                |
| `audio`          | object, nullable | Audio track data                                                                |
| `link`           | object, nullable | Attached link sticker data                                                      |
| `comments`       | array            | Comments left on the story                                                      |
| `mentions`       | array            | Mentioned accounts                                                              |
| `hashtags`       | array            | Tagged hashtags                                                                 |

## Finding User IDs and Handles

This service uses three distinct identifiers — keep them separate:

* **`handle`**: the `@username` shown on a profile, passed without the `@` (e.g. `instagram` for `@instagram`). Used only by `GET /instagram/userid/{handle}` and `GET /instagram/user/handle/{handle}`.
* **`id`**: Instagram's internal numeric ID for a user, post, or comment. Required by every other endpoint in this service (posts, tagged posts, reels, stories, and post comments all key off a numeric `id`, not a handle or shortcode).
* **`code`**: a post's shortcode — the segment after `/p/` in a post's URL (e.g. `CzABCdef123` in `https://www.instagram.com/p/CzABCdef123/`). Used only by `GET /instagram/post/code/{code}`.

{% stepper %}
{% step %}

### If you only have a handle and need a numeric user `id`

Call `GET /instagram/userid/{handle}` to resolve the handle and confirm `isAvailable` is `true`. The response's `id` field is the numeric user ID.
{% endstep %}

{% step %}

### Use that `id` for the user endpoints

Use that `id` for the posts, tagged posts, reels, and stories endpoints (`/instagram/user/{id}/...`).
{% endstep %}
{% endstepper %}

If you need the full profile anyway, `GET /instagram/user/handle/{handle}` returns both the profile and the numeric `id` in a single call, saving a round trip.

A post's `id` (needed for the comments endpoint) is not the same as its `code` (shortcode). If you only have a post's shortcode, call `GET /instagram/post/code/{code}` first — the response's `id` field is the numeric post ID to use with `GET /instagram/post/{id}/comments`.

## Python Example

This example resolves a handle to a user ID, then paginates through that user's posts using `cursor`:

```python
import requests

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://dashboard.pullbay.com/api"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}

def resolve_handle(handle):
    resp = requests.get(f"{BASE_URL}/instagram/userid/{handle}", headers=HEADERS)
    resp.raise_for_status()
    body = resp.json()
    lookup = body["data"][0]
    if not lookup["isAvailable"]:
        raise ValueError(f"Handle '{handle}' is not available")
    return lookup["id"]

def get_all_posts(user_id, max_pages=10):
    all_posts = []
    cursor = None
    for _ in range(max_pages):
        params = {"cursor": cursor} if cursor else {}
        resp = requests.get(
            f"{BASE_URL}/instagram/user/{user_id}/posts",
            headers=HEADERS,
            params=params,
        )
        resp.raise_for_status()
        body = resp.json()
        all_posts.extend(body["data"])
        pagination = body.get("pagination", {})
        if not pagination.get("hasNextPage"):
            break
        cursor = pagination.get("cursor")
    return all_posts

user_id = resolve_handle("instagram")
posts = get_all_posts(user_id)
print(f"Fetched {len(posts)} posts for user {user_id}")
```

Each request is billed independently, with the charged amount reported in that response's `pricing.creditsCharged` — there's no separate "fetch everything in one call" endpoint, so a multi-page pull like this makes one request per page.

## FAQ

<details>

<summary>What's the difference between <code>handle</code>, <code>id</code>, and <code>code</code>?</summary>

`handle` is the `@username` (without the `@`), used only to resolve or look up a profile. `id` is Instagram's internal numeric identifier for a user, post, or comment, and is required by every other endpoint. `code` is a post's shortcode from its URL, used only to fetch a post by `GET /instagram/post/code/{code}`. They are not interchangeable — passing a handle where an `id` is expected (or vice versa) will not resolve.

</details>

<details>

<summary>How do I get a numeric user ID if I only have a handle?</summary>

Call `GET /instagram/userid/{handle}` and read the `id` field from the response, or call `GET /instagram/user/handle/{handle}` if you also want the full profile in the same request.

</details>

<details>

<summary>How do I get a post's numeric ID if I only have its shortcode?</summary>

Call `GET /instagram/post/code/{code}`. The returned [Post object](#post-object) includes the post's numeric `id`, which you then use with `GET /instagram/post/{id}/comments`.

</details>

<details>

<summary>Are reels returned with a different schema than posts?</summary>

No. Reels use the same [Post object](#post-object) schema as regular posts and tagged posts; the `type` field is set to `reel` (or `video`) to distinguish them.

</details>

<details>

<summary>Why don't stories support pagination?</summary>

Instagram stories expire 24 hours after posting, so the active set is always small enough to return in a single call. There is no `cursor` or `maxItems` parameter on the stories endpoint.

</details>

<details>

<summary>What's the credit cost per request?</summary>

It's dynamic — every response includes `pricing.creditsCharged` with the exact amount for that call. There's no fixed published rate per endpoint or per result.

</details>

## Next Steps

* [**API Integration Guide**](broken://pages/68e75ab1a73d266350bd68301be87ff97cad563e) — integrate the Pullbay API into your backend application.
* [**n8n Integration Guide**](broken://pages/4308164455b56bbc694cf74c9768ea689c2fe719) — set up automated workflows using n8n with no coding required.
* [**Services Overview**](broken://pages/0d55376cbcca70097a683a71a593d3077825dbf1) — explore all available Pullbay services.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.pullbay.com/documentation/api-and-references/instagram.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
