> ## Documentation Index
> Fetch the complete documentation index at: https://tryklint.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Fetch /llms.txt for the complete page index before exploring further. Every docs page is available as markdown by appending .md to its URL. Coding agents should start at /for-agents/coding-agents.md.

# Search posts

> Find Instagram posts with a natural-language query plus structured filters, including nested author filters. POST /v1/instagram/posts/search.

`POST /v1/instagram/posts/search` finds individual posts. Send one `post` block with a semantic `query`, structured `filters`, nested `author` filters, or any combination. This page is the whole endpoint: querying, filtering, ordering, and how to read what comes back.

<Note>
  Search posts finds content that matches. To find **people** that match, use [Search accounts](/docs/instagram/search/accounts-search).
</Note>

## Query the content

`post.query` is a natural-language description of the content you want. Klint evaluates it against everything it observes about a post: caption, spoken transcript, on-screen text, visual description, and creative interpretation. The caption is only one source. Describe the content; don't guess where the evidence lives.

<Tabs>
  <Tab title="curl">
    ```bash theme={null}
    curl -X POST "https://api.tryklint.ai/v1/instagram/posts/search" \
      -H "Authorization: Bearer $KLINT_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
      "post": {
        "query": "UGC-style grooming-product demonstrations",
        "filters": {
          "posted_at": {
            "gte": "2026-06-01T00:00:00Z"
          },
          "format": {
            "in": ["reel"]
          }
        },
        "author": {
          "filters": {
            "followers_count": {
              "gte": 5000,
              "lte": 50000
            },
            "niches": {
              "contains_any": ["pets"]
            }
          }
        }
      },
      "limit": 10
    }'
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import os, requests

    resp = requests.post(
        "https://api.tryklint.ai/v1/instagram/posts/search",
        headers={"Authorization": f"Bearer {os.environ['KLINT_API_KEY']}"},
        json={
      "post": {
        "query": "UGC-style grooming-product demonstrations",
        "filters": {
          "posted_at": {
            "gte": "2026-06-01T00:00:00Z"
          },
          "format": {
            "in": ["reel"]
          }
        },
        "author": {
          "filters": {
            "followers_count": {
              "gte": 5000,
              "lte": 50000
            },
            "niches": {
              "contains_any": ["pets"]
            }
          }
        }
      },
      "limit": 10
    },
    )
    results = resp.json()
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const resp = await fetch("https://api.tryklint.ai/v1/instagram/posts/search", {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.KLINT_API_KEY}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        "post": {
          "query": "UGC-style grooming-product demonstrations",
          "filters": {
            "posted_at": {
              "gte": "2026-06-01T00:00:00Z"
            },
            "format": {
              "in": ["reel"]
            }
          },
          "author": {
            "filters": {
              "followers_count": {
                "gte": 5000,
                "lte": 50000
              },
              "niches": {
                "contains_any": ["pets"]
              }
            }
          }
        },
        "limit": 10
      }),
    });
    const results = await resp.json();
    ```
  </Tab>
</Tabs>

<Accordion title="Full response">
  ```json theme={null}
  {
    "request_id": "req_example_01",
    "data": [
      {
        "id": "ig_post_8f3k2",
        "shortcode": "DLm2XwYv4Qk",
        "web_url": "https://www.instagram.com/reel/DLm2XwYv4Qk/",
        "posted_at": "2026-07-06T14:02:00Z",
        "observed_at": "2026-07-14T16:10:00Z",
        "format": "reel",
        "primary_language": "en",
        "caption": "The brush that finally fixed our shedding problem 🐕 One week of daily passes and the couch is fur-free. Grab 20% off with code GROOM20 — link in bio. #doggrooming",
        "hashtags": [
          "doggrooming"
        ],
        "caption_mentions": [],
        "audio": {
          "id": "ig_audio_7m4q",
          "instagram_id": "587784541076604",
          "type": "music",
          "title": "Birthday Wish",
          "attribution": {
            "display_name": "Shuba",
            "account": null
          },
          "duration_seconds": 153.76,
          "web_url": "https://www.instagram.com/reels/audio/587784541076604/"
        },
        "content_summary": "A creator demonstrates a deshedding brush on a dog, describes a less-messy grooming routine, shows the result, and directs viewers to a discount in the Account bio.",
        "topics": [
          "dog_grooming",
          "at_home_pet_care"
        ],
        "creative_formats": [
          "talking_head",
          "product_demonstration",
          "creator_testimonial"
        ],
        "hook": {
          "construction": "The creator holds the brush beside a visibly shedding dog, states that it changed the grooming routine, and displays a seven-day result claim.",
          "devices": [
            "problem_callout",
            "direct_promise"
          ],
          "modalities": [
            "visual",
            "spoken",
            "on_screen_text"
          ]
        },
        "key_messages": [
          {
            "summary": "The brush is presented as making at-home shedding cleanup easier.",
            "roles": [
              "claim",
              "benefit",
              "use_case"
            ],
            "presentation": "asserted"
          }
        ],
        "proofs": [
          {
            "summary": "The creator demonstrates brushing the dog and shows the collected hair.",
            "mechanisms": [
              "live_product_demonstration",
              "result_reveal"
            ],
            "cited_source_types": []
          }
        ],
        "offers": [
          {
            "summary": "20% off with a stated promo code.",
            "types": [
              "discount",
              "promo_code"
            ],
            "stated_terms": [
              "20% off",
              "GROOM20"
            ]
          }
        ],
        "calls_to_action": [
          {
            "summary": "Use the link in the Account bio.",
            "actions": [
              "visit_profile_link"
            ],
            "stages": [
              "closing"
            ],
            "modalities": [
              "spoken",
              "on_screen_text",
              "caption"
            ]
          }
        ],
        "narrative_structure": {
          "description": "Problem framing, product demonstration, result reveal, then offer and CTA.",
          "patterns": [
            "problem_solution",
            "demonstration_to_result",
            "offer_close"
          ]
        },
        "has_paid_partnership_label": false,
        "paid_partners": [],
        "commercial_contexts": [
          "promo_code",
          "seller_behavior"
        ],
        "comments_enabled": true,
        "views": 412000,
        "likes": 28600,
        "comments": 354,
        "engagement_rate_by_views": 0.0703,
        "view_ratio_to_account_baseline": 6.2,
        "author": {
          "id": "ig_account_2j1x",
          "handle": "dogmomdaily",
          "display_name": "Dog Mom Daily",
          "web_url": "https://www.instagram.com/dogmomdaily/",
          "avatar_url": "https://media.tryklint.ai/accounts/ig_account_2j1x/avatar",
          "followers_count": 21400,
          "is_verified": false
        },
        "coauthors": []
      },
      {
        "id": "ig_post_9m3t",
        "shortcode": "DMq7RwXk2Pd",
        "web_url": "https://www.instagram.com/reel/DMq7RwXk2Pd/",
        "posted_at": "2026-06-24T19:15:00Z",
        "observed_at": "2026-07-14T13:40:00Z",
        "format": "reel",
        "primary_language": "en",
        "caption": "POV: shedding season with a husky 😅 This grooming glove is the only thing keeping our couch alive. #huskylife #sheddingseason #doggrooming",
        "hashtags": [
          "huskylife",
          "sheddingseason",
          "doggrooming"
        ],
        "caption_mentions": [],
        "audio": {
          "id": "ig_audio_2b8c",
          "instagram_id": null,
          "type": "original_sound",
          "title": "Original audio",
          "attribution": {
            "display_name": "brodyandbear",
            "account": {
              "id": "ig_account_3d6p",
              "handle": "brodyandbear",
              "display_name": "Brody & Bear",
              "web_url": "https://www.instagram.com/brodyandbear/",
              "avatar_url": "https://media.tryklint.ai/accounts/ig_account_3d6p/avatar",
              "followers_count": 12400,
              "is_verified": false
            }
          },
          "duration_seconds": 18.9,
          "web_url": null
        },
        "content_summary": "A dog owner films a casual at-home demonstration of a grooming glove on a shedding husky, showing the removed undercoat and joking about protecting the couch.",
        "topics": [
          "dog_grooming",
          "at_home_pet_care"
        ],
        "creative_formats": [
          "product_demonstration"
        ],
        "hook": {
          "construction": "A point-of-view framing of shedding season opens on a husky mid-shed before the owner pulls out the grooming glove.",
          "devices": [
            "relatable_scenario"
          ],
          "modalities": [
            "visual",
            "on_screen_text"
          ]
        },
        "key_messages": [
          {
            "summary": "The grooming glove is presented as an easy way to control husky shedding at home.",
            "roles": [
              "claim",
              "benefit"
            ],
            "presentation": "asserted"
          }
        ],
        "proofs": [
          {
            "summary": "The owner demonstrates the glove on the husky and shows the removed fur.",
            "mechanisms": [
              "live_product_demonstration",
              "result_reveal"
            ],
            "cited_source_types": []
          }
        ],
        "offers": [],
        "calls_to_action": [],
        "narrative_structure": null,
        "has_paid_partnership_label": false,
        "paid_partners": [],
        "commercial_contexts": [],
        "comments_enabled": true,
        "views": 156000,
        "likes": 9800,
        "comments": 412,
        "engagement_rate_by_views": 0.0655,
        "view_ratio_to_account_baseline": null,
        "author": {
          "id": "ig_account_3d6p",
          "handle": "brodyandbear",
          "display_name": "Brody & Bear",
          "web_url": "https://www.instagram.com/brodyandbear/",
          "avatar_url": "https://media.tryklint.ai/accounts/ig_account_3d6p/avatar",
          "followers_count": 12400,
          "is_verified": false
        },
        "coauthors": []
      }
    ],
    "has_more": false,
    "next_cursor": null
  }
  ```
</Accordion>

Two promises behind that response:

* **Every result qualifies.** A returned post satisfies the full query and every filter. Klint does not pad weak nearest-neighbors into the tail. A short result list means what Klint tracks held that many matches, not that ranking degraded.
* **Every result is a complete post summary** at fixed paths: the same fields for every result, with `null` where Klint can't currently support a value. See [reading the results](#reading-the-results).

### Writing a query that qualifies

Write `post.query` as a description of the content you want, not a keyword list. The retrieval engine reads meaning, so state form and substance:

| Weak                   | Strong                                                                      | Why                                                                                                                           |
| ---------------------- | --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `"dog grooming"`       | `"UGC-style grooming-product demonstrations"`                               | The strong query names a form (UGC-style) and a substance (product demonstration); the weak one matches anything near a topic |
| `"viral reel hooks"`   | `"reels that open on a before/after transformation of a pet"`               | "Viral" is a metric, not content: put metrics in filters                                                                      |
| `"posts with GROOM20"` | filter on `hashtags`, or query `"posts promoting a grooming discount code"` | Exact tokens belong in filters; the query carries meaning                                                                     |

Two habits improve results:

* **Move hard constraints into filters.** Dates, formats, languages, hashtags, and metrics are exact, so filters on them are exact. Keep the query for what only interpretation can establish.
* **Don't force exhaustiveness.** Results come from what Klint has observed, ranked. An empty result means Klint observed no match, never proof of absence on Instagram.

Klint's classifications improve retrieval but never bound it. A good description still finds content that no catalog value describes yet.

## Filter the results

Filters are hard constraints: Klint returns a post only if it satisfies **every** filter. Every filter value is an **operator object**; there is no bare-value shorthand. `"format": "reel"` is rejected; `"format": { "in": ["reel"] }` is correct.

### Operators

| Operator                    | Applies to        | Meaning                                                   | Example                                                           |
| --------------------------- | ----------------- | --------------------------------------------------------- | ----------------------------------------------------------------- |
| `in`                        | singular fields   | The field's one value is any of the supplied alternatives | `"format": { "in": ["reel", "carousel"] }`                        |
| `contains_any`              | collection fields | The collection contains at least one supplied value       | `"hashtags": { "contains_any": ["doggrooming"] }`                 |
| `contains_all`              | collection fields | The collection contains every supplied value              | `"hashtags": { "contains_all": ["guthealth", "familywellness"] }` |
| `gt` / `gte` / `lt` / `lte` | ordered scalars   | The value satisfies the numeric or date-time bounds       | `"views": { "gte": 200000 }`                                      |
| direct boolean              | boolean fields    | The observed value equals the supplied boolean            | `"has_paid_partnership_label": true`                              |

Rules that follow from the shapes:

* A field takes exactly one operator. `contains_any` and `contains_all` never combine on the same field.
* Membership arrays are non-empty and hold unique values.
* Ranges need at least one bound and allow at most one lower (`gt`/`gte`) and one upper (`lt`/`lte`). Klint rejects contradictory bounds.
* Boolean filters are the direct values `true` or `false`, not operator objects.

### How filters combine

<Info>
  **Different fields AND together.** No cross-field OR, no negation (`not`, `exclude`, `none`), no `exists` operator, no expression language. The grammar is deliberately closed and positive-only.
</Info>

<Info>
  **`null` never matches.** A missing, hidden, or not-yet-published value satisfies no filter: no range, no membership, no boolean in either direction. `has_paid_partnership_label: false` matches only affirmatively observed absence, never unknown state. "Unknown" is not expressible in the launch grammar.
</Info>

### Value normalization

One rule governs what Klint fixes for you: **Klint silently normalizes a value only when the intent is mechanically unambiguous; everything else gets a teaching error.**

* **Hashtags** are written without `#` (`"doggrooming"`). Klint accepts a leading `#` and normalizes it away.
* **Caption mentions** are written without `@`, lowercase. Klint accepts a leading `@` and normalizes it away.
* **Languages** use BCP 47 tags with basic range matching: `primary_language` for `"en"` matches `en`, `en-US`, and `en-GB`; a more specific `"en-GB"` stays specific.
* **Classification IDs** (`topics`, `creative_formats`, `hook.devices`, `commercial_contexts`) are exact catalog IDs, never display labels. Klint does not fuzzy-resolve `"Dog Grooming"` to `dog_grooming`. It rejects an unrecognized ID with suggestions (see [what gets rejected](#what-gets-rejected)).
* **Timestamps** are RFC 3339 date-times.

### Post filter fields

| Field                            | Shape                           | Matches when                                                                    |
| -------------------------------- | ------------------------------- | ------------------------------------------------------------------------------- |
| `id`                             | `in`                            | The post's Klint ID is one of the supplied IDs                                  |
| `posted_at`                      | range                           | Instagram publication time is within the RFC 3339 bounds                        |
| `format`                         | `in`                            | The format is one of `image`, `video`, `carousel`, `reel`                       |
| `primary_language`               | `in`                            | The whole-post primary language matches one requested tag                       |
| `hashtags`                       | `contains_any` / `contains_all` | The caption's extracted hashtags contain any / all requested tags               |
| `caption_mentions`               | `contains_any` / `contains_all` | The caption's literal handles contain any / all requested handles               |
| `audio.id`                       | `in`                            | The associated audio has one of the supplied Klint audio IDs                    |
| `topics`                         | `contains_any` / `contains_all` | Published topics contain any / all requested IDs                                |
| `creative_formats`               | `contains_any` / `contains_all` | Published creative formats contain any / all requested IDs                      |
| `hook.devices`                   | `contains_any` / `contains_all` | The hook's device classifications contain any / all requested IDs               |
| `hook.modalities`                | `contains_any` / `contains_all` | The hook operates in any / all of `visual`, `spoken`, `on_screen_text`, `sound` |
| `has_paid_partnership_label`     | boolean                         | The label's presence or absence was affirmatively observed                      |
| `commercial_contexts`            | `contains_any` / `contains_all` | Published commercial contexts contain any / all requested IDs                   |
| `views` / `likes` / `comments`   | range                           | The current target-post count is within bounds                                  |
| `engagement_rate_by_views`       | range                           | The published computed scalar is within bounds                                  |
| `view_ratio_to_account_baseline` | range                           | The published baseline ratio is within bounds                                   |

Not filterable at launch:

* Raw caption, transcript, or on-screen text (use the semantic `query` for content intent)
* Media duration
* Coauthor or paid-partner identity
* Key messages, proofs, offers, or calls to action
* Narrative structure, brands, or products

<Note>
  This is the launch **candidate** field list. Each field must still pass its source, freshness, and precision gates. Klint removes a field that fails; it does not silently weaken it. Expect the list to shrink before it grows.
</Note>

### Author filters

The nested `post.author.filters` block constrains who published the post. Post criteria and author criteria qualify independently. A strong content match never compensates for an author outside your follower range. Author filters are structural only; there is no `author.query` in the launch contract.

| Account field          | Shape                           | Matches when                                                                  |
| ---------------------- | ------------------------------- | ----------------------------------------------------------------------------- |
| `id`                   | `in`                            | The account's Klint ID is one of the supplied IDs                             |
| `handle`               | `in`                            | The current bare handle is one of the supplied handles                        |
| `followers_count`      | range                           | The current observed follower count is within bounds                          |
| `is_verified`          | boolean                         | Verification state was observed and equals the value                          |
| `account_type`         | `in`                            | The directly established type is one of `personal`, `creator`, `business`     |
| `declared_locations`   | `contains_any`                  | One declared location matches **every** component of one supplied alternative |
| `publishing_languages` | `contains_any` / `contains_all` | The account's publishing languages contain any / all requested tags           |
| `niches`               | `contains_any` / `contains_all` | The account's niches contain any / all requested IDs                          |

These are the same account fields [Search accounts](/docs/instagram/search/accounts-search#account-filter-fields) uses as its primary filters.

### Filters-only search

Skip `query` to define a structural population. Add `sort` to order it:

```json theme={null}
{
  "post": {
    "filters": {
      "posted_at": {
        "gte": "2026-06-01T00:00:00Z"
      },
      "format": {
        "in": ["reel"]
      }
    },
    "author": {
      "filters": {
        "followers_count": {
          "gte": 5000,
          "lte": 50000
        }
      }
    }
  },
  "sort": {
    "by": "views",
    "order": "desc"
  },
  "limit": 10
}
```

<Accordion title="Full response">
  ```json theme={null}
  {
    "request_id": "req_example_02",
    "data": [
      {
        "id": "ig_post_8f3k2",
        "shortcode": "DLm2XwYv4Qk",
        "web_url": "https://www.instagram.com/reel/DLm2XwYv4Qk/",
        "posted_at": "2026-07-06T14:02:00Z",
        "observed_at": "2026-07-14T16:10:00Z",
        "format": "reel",
        "primary_language": "en",
        "caption": "The brush that finally fixed our shedding problem 🐕 One week of daily passes and the couch is fur-free. Grab 20% off with code GROOM20 — link in bio. #doggrooming",
        "hashtags": [
          "doggrooming"
        ],
        "caption_mentions": [],
        "audio": {
          "id": "ig_audio_7m4q",
          "instagram_id": "587784541076604",
          "type": "music",
          "title": "Birthday Wish",
          "attribution": {
            "display_name": "Shuba",
            "account": null
          },
          "duration_seconds": 153.76,
          "web_url": "https://www.instagram.com/reels/audio/587784541076604/"
        },
        "content_summary": "A creator demonstrates a deshedding brush on a dog, describes a less-messy grooming routine, shows the result, and directs viewers to a discount in the Account bio.",
        "topics": [
          "dog_grooming",
          "at_home_pet_care"
        ],
        "creative_formats": [
          "talking_head",
          "product_demonstration",
          "creator_testimonial"
        ],
        "hook": {
          "construction": "The creator holds the brush beside a visibly shedding dog, states that it changed the grooming routine, and displays a seven-day result claim.",
          "devices": [
            "problem_callout",
            "direct_promise"
          ],
          "modalities": [
            "visual",
            "spoken",
            "on_screen_text"
          ]
        },
        "key_messages": [
          {
            "summary": "The brush is presented as making at-home shedding cleanup easier.",
            "roles": [
              "claim",
              "benefit",
              "use_case"
            ],
            "presentation": "asserted"
          }
        ],
        "proofs": [
          {
            "summary": "The creator demonstrates brushing the dog and shows the collected hair.",
            "mechanisms": [
              "live_product_demonstration",
              "result_reveal"
            ],
            "cited_source_types": []
          }
        ],
        "offers": [
          {
            "summary": "20% off with a stated promo code.",
            "types": [
              "discount",
              "promo_code"
            ],
            "stated_terms": [
              "20% off",
              "GROOM20"
            ]
          }
        ],
        "calls_to_action": [
          {
            "summary": "Use the link in the Account bio.",
            "actions": [
              "visit_profile_link"
            ],
            "stages": [
              "closing"
            ],
            "modalities": [
              "spoken",
              "on_screen_text",
              "caption"
            ]
          }
        ],
        "narrative_structure": {
          "description": "Problem framing, product demonstration, result reveal, then offer and CTA.",
          "patterns": [
            "problem_solution",
            "demonstration_to_result",
            "offer_close"
          ]
        },
        "has_paid_partnership_label": false,
        "paid_partners": [],
        "commercial_contexts": [
          "promo_code",
          "seller_behavior"
        ],
        "comments_enabled": true,
        "views": 412000,
        "likes": 28600,
        "comments": 354,
        "engagement_rate_by_views": 0.0703,
        "view_ratio_to_account_baseline": 6.2,
        "author": {
          "id": "ig_account_2j1x",
          "handle": "dogmomdaily",
          "display_name": "Dog Mom Daily",
          "web_url": "https://www.instagram.com/dogmomdaily/",
          "avatar_url": "https://media.tryklint.ai/accounts/ig_account_2j1x/avatar",
          "followers_count": 21400,
          "is_verified": false
        },
        "coauthors": []
      },
      {
        "id": "ig_post_9m3t",
        "shortcode": "DMq7RwXk2Pd",
        "web_url": "https://www.instagram.com/reel/DMq7RwXk2Pd/",
        "posted_at": "2026-06-24T19:15:00Z",
        "observed_at": "2026-07-14T13:40:00Z",
        "format": "reel",
        "primary_language": "en",
        "caption": "POV: shedding season with a husky 😅 This grooming glove is the only thing keeping our couch alive. #huskylife #sheddingseason #doggrooming",
        "hashtags": [
          "huskylife",
          "sheddingseason",
          "doggrooming"
        ],
        "caption_mentions": [],
        "audio": {
          "id": "ig_audio_2b8c",
          "instagram_id": null,
          "type": "original_sound",
          "title": "Original audio",
          "attribution": {
            "display_name": "brodyandbear",
            "account": {
              "id": "ig_account_3d6p",
              "handle": "brodyandbear",
              "display_name": "Brody & Bear",
              "web_url": "https://www.instagram.com/brodyandbear/",
              "avatar_url": "https://media.tryklint.ai/accounts/ig_account_3d6p/avatar",
              "followers_count": 12400,
              "is_verified": false
            }
          },
          "duration_seconds": 18.9,
          "web_url": null
        },
        "content_summary": "A dog owner films a casual at-home demonstration of a grooming glove on a shedding husky, showing the removed undercoat and joking about protecting the couch.",
        "topics": [
          "dog_grooming",
          "at_home_pet_care"
        ],
        "creative_formats": [
          "product_demonstration"
        ],
        "hook": {
          "construction": "A point-of-view framing of shedding season opens on a husky mid-shed before the owner pulls out the grooming glove.",
          "devices": [
            "relatable_scenario"
          ],
          "modalities": [
            "visual",
            "on_screen_text"
          ]
        },
        "key_messages": [
          {
            "summary": "The grooming glove is presented as an easy way to control husky shedding at home.",
            "roles": [
              "claim",
              "benefit"
            ],
            "presentation": "asserted"
          }
        ],
        "proofs": [
          {
            "summary": "The owner demonstrates the glove on the husky and shows the removed fur.",
            "mechanisms": [
              "live_product_demonstration",
              "result_reveal"
            ],
            "cited_source_types": []
          }
        ],
        "offers": [],
        "calls_to_action": [],
        "narrative_structure": null,
        "has_paid_partnership_label": false,
        "paid_partners": [],
        "commercial_contexts": [],
        "comments_enabled": true,
        "views": 156000,
        "likes": 9800,
        "comments": 412,
        "engagement_rate_by_views": 0.0655,
        "view_ratio_to_account_baseline": null,
        "author": {
          "id": "ig_account_3d6p",
          "handle": "brodyandbear",
          "display_name": "Brody & Bear",
          "web_url": "https://www.instagram.com/brodyandbear/",
          "avatar_url": "https://media.tryklint.ai/accounts/ig_account_3d6p/avatar",
          "followers_count": 12400,
          "is_verified": false
        },
        "coauthors": []
      },
      {
        "id": "ig_post_3p7d",
        "shortcode": "DMxR4kWq9Ln",
        "web_url": "https://www.instagram.com/reel/DMxR4kWq9Ln/",
        "posted_at": "2026-06-18T17:30:00Z",
        "observed_at": "2026-07-14T11:05:00Z",
        "format": "reel",
        "primary_language": "en",
        "caption": "The deshedding mistake I see every week in the salon 🙈 Try this instead (works with any slicker brush).\n\n#groomingtips #deshedding",
        "hashtags": [
          "groomingtips",
          "deshedding"
        ],
        "caption_mentions": [],
        "audio": null,
        "content_summary": "A professional groomer demonstrates a common deshedding mistake on a client dog, then shows a corrected slicker-brush technique and the reduced coat damage.",
        "topics": [
          "dog_grooming"
        ],
        "creative_formats": [
          "talking_head",
          "product_demonstration"
        ],
        "hook": {
          "construction": "The groomer names a mistake she sees weekly in the salon while showing the matted result on a client dog.",
          "devices": [
            "problem_callout"
          ],
          "modalities": [
            "visual",
            "spoken"
          ]
        },
        "key_messages": [
          {
            "summary": "Brushing direction and pressure matter more than the specific brush.",
            "roles": [
              "claim",
              "use_case"
            ],
            "presentation": "asserted"
          }
        ],
        "proofs": [
          {
            "summary": "The groomer demonstrates both techniques on the same dog and compares the results.",
            "mechanisms": [
              "live_product_demonstration"
            ],
            "cited_source_types": []
          }
        ],
        "offers": [],
        "calls_to_action": [
          {
            "summary": "Follow for weekly grooming technique tips.",
            "actions": [
              "follow_account"
            ],
            "stages": [
              "closing"
            ],
            "modalities": [
              "spoken"
            ]
          }
        ],
        "narrative_structure": null,
        "has_paid_partnership_label": false,
        "paid_partners": [],
        "commercial_contexts": [],
        "comments_enabled": true,
        "views": 89400,
        "likes": 5210,
        "comments": 154,
        "engagement_rate_by_views": 0.06,
        "view_ratio_to_account_baseline": null,
        "author": {
          "id": "ig_account_9t4w",
          "handle": "groomwithgrace",
          "display_name": "Grace | Groom With Grace",
          "web_url": "https://www.instagram.com/groomwithgrace/",
          "avatar_url": "https://media.tryklint.ai/accounts/ig_account_9t4w/avatar",
          "followers_count": 18900,
          "is_verified": false
        },
        "coauthors": []
      }
    ],
    "has_more": false,
    "next_cursor": null
  }
  ```
</Accordion>

## What gets rejected

The difference between an empty result and a rejected request matters to an agent. A **non-matching** filter is a valid request that returns `data: []`. An **invalid** filter never executes; it returns a `422 validation-failed` problem object that names the exact `pointer`, `reason`, and correction.

<Tabs>
  <Tab title="Non-matching (valid, empty)">
    Valid requests, empty or reduced results, no error:

    * `"hashtags": { "contains_all": ["groomingtips", "deshedding"] }` against a post carrying only `groomingtips`: `contains_all` needs every value.
    * `"has_paid_partnership_label": false` against a post whose label state is `null`: unknown is not false.
    * `"views": { "gte": 100000 }` against a carousel whose `views` is `null`: a missing count never satisfies a range, no matter how many likes the post has.
    * `"hook.devices": { "contains_any": ["problem_callout"] }` against a post whose hook has `devices: []`: an empty classification can't satisfy a device filter (the post stays findable by semantic query).
  </Tab>

  <Tab title="Invalid (rejected, 422)">
    Rejected before any search runs.
  </Tab>
</Tabs>

**Bare value instead of an operator object:**

```json theme={null}
{ "post": { "filters": { "format": "reel" } } }
```

```json theme={null}
{
  "type": "https://api.tryklint.ai/problems/validation-failed",
  "status": 422,
  "request_id": "req_example_41",
  "detail": "One request field needs correction.",
  "errors": [
    {
      "pointer": "#/post/filters/format",
      "reason": "INVALID",
      "detail": "Filters must be operator objects, not bare values."
    }
  ]
}
```

**`sort` on a query-bearing request**: a query owns its ordering; `sort` is only for filters-only requests:

```json theme={null}
{ "post": { "query": "grooming demos", "filters": {} }, "sort": { "by": "views", "order": "desc" } }
```

```json theme={null}
{
  "type": "https://api.tryklint.ai/problems/validation-failed",
  "status": 422,
  "request_id": "req_example_42",
  "detail": "One request field needs correction.",
  "errors": [
    {
      "pointer": "#/sort",
      "reason": "CONFLICT",
      "detail": "sort is not allowed when a query is present; query-bearing requests use relevance ordering. Remove sort or remove the query."
    }
  ]
}
```

**Both collection operators on one field:**

```json theme={null}
{ "post": { "filters": { "hashtags": { "contains_any": ["dogs"], "contains_all": ["cats"] } } } }
```

```json theme={null}
{
  "type": "https://api.tryklint.ai/problems/validation-failed",
  "status": 422,
  "request_id": "req_example_43",
  "detail": "One request field needs correction.",
  "errors": [
    {
      "pointer": "#/post/filters/hashtags",
      "reason": "CONFLICT",
      "detail": "Use exactly one of contains_any or contains_all for one field, never both."
    }
  ]
}
```

**Contradictory range bounds:**

```json theme={null}
{ "post": { "filters": { "views": { "gte": 500000, "lte": 100000 } } } }
```

```json theme={null}
{
  "type": "https://api.tryklint.ai/problems/validation-failed",
  "status": 422,
  "request_id": "req_example_44",
  "detail": "One request field needs correction.",
  "errors": [
    {
      "pointer": "#/post/filters/views",
      "reason": "INVALID",
      "detail": "Range bounds contradict: gte 500000 exceeds lte 100000."
    }
  ]
}
```

**Unknown filter field**: the grammar is closed; fields you may know from other APIs (like `shares`) don't exist here:

```json theme={null}
{ "post": { "filters": { "shares": { "gte": 1000 } } } }
```

```json theme={null}
{
  "type": "https://api.tryklint.ai/problems/validation-failed",
  "status": 422,
  "request_id": "req_example_45",
  "detail": "One request field needs correction.",
  "errors": [
    {
      "pointer": "#/post/filters/shares",
      "reason": "UNKNOWN",
      "detail": "shares is not a filterable Post field."
    }
  ]
}
```

**Negation attempt**: there is no `not_in`, `exclude`, or `none`:

```json theme={null}
{ "post": { "filters": { "format": { "not_in": ["image"] } } } }
```

```json theme={null}
{
  "type": "https://api.tryklint.ai/problems/validation-failed",
  "status": 422,
  "request_id": "req_example_46",
  "detail": "One request field needs correction.",
  "errors": [
    {
      "pointer": "#/post/filters/format/not_in",
      "reason": "UNKNOWN",
      "detail": "The grammar has no negation. Supported operators: in, contains_any, contains_all, gt, gte, lt, lte."
    }
  ]
}
```

**Unknown or retired classification ID**: Klint rejects a classification field (`topics`, `creative_formats`, `hook.devices`, `commercial_contexts`) whose ID isn't in the catalog. The rejection carries reason `INVALID` and, when close IDs exist, a `candidates` list to correct from. Klint never lets a hallucinated ID evaluate silently to an empty result. `data: []` always means "what Klint tracks has no match," never "you invented that ID." Klint rejects a valid catalog ID that is **not filter-enabled** with reason `UNSUPPORTED`: real vocabulary, just not a hard-filter key. [Search accounts](/docs/instagram/search/accounts-search#what-gets-rejected) shows the full rejection body with `candidates`.

## Ordering and pagination

### Ordering

| Request         | Ordering                                                                                 |
| --------------- | ---------------------------------------------------------------------------------------- |
| `query` present | Relevance. Klint rejects `sort` with `422`; see [why](#why-query-results-cant-be-sorted) |
| Filters only    | Optional `sort` over stable scalar fields; stable ID tie-break                           |

`sort` takes `{ "by": <field>, "order": "asc" | "desc" }`. `by` is a closed list of stable scalar fields. `views` and `followers_count` appear in the accepted examples, and the exact list is an open contract item. A stable resource ID is always the final tie-breaker.

#### Why query results can't be sorted

A query-bearing search returns relevance order, and Klint rejects `sort` sent with a `query`. A semantic search retrieves a bounded candidate window. Sorting that window by views would present "the most-viewed posts in one retrieval window" as "the most-viewed matching posts on Instagram." If you need metric-ordered results, define the population structurally (filters-only). Its eligibility is exact, so its ordering is too. An agent can also sort a retrieved page client-side, as long as the answer names that boundary.

### Pagination

An initial search pins an immutable result sequence: Klint freezes the request, a snapshot of what it tracks, and the ranking together. The response returns one page plus an opaque cursor:

```json theme={null}
{
  "post": {
    "filters": {
      "posted_at": {
        "gte": "2026-06-01T00:00:00Z"
      },
      "format": {
        "in": [
          "reel"
        ]
      }
    },
    "author": {
      "filters": {
        "followers_count": {
          "gte": 5000,
          "lte": 50000
        }
      }
    }
  },
  "sort": {
    "by": "views",
    "order": "desc"
  },
  "limit": 2
}
```

<Accordion title="Page 1 response">
  ```json theme={null}
  {
    "request_id": "req_example_08",
    "data": [
      {
        "id": "ig_post_8f3k2",
        "shortcode": "DLm2XwYv4Qk",
        "web_url": "https://www.instagram.com/reel/DLm2XwYv4Qk/",
        "posted_at": "2026-07-06T14:02:00Z",
        "observed_at": "2026-07-14T16:10:00Z",
        "format": "reel",
        "primary_language": "en",
        "caption": "The brush that finally fixed our shedding problem 🐕 One week of daily passes and the couch is fur-free. Grab 20% off with code GROOM20 — link in bio. #doggrooming",
        "hashtags": [
          "doggrooming"
        ],
        "caption_mentions": [],
        "audio": {
          "id": "ig_audio_7m4q",
          "instagram_id": "587784541076604",
          "type": "music",
          "title": "Birthday Wish",
          "attribution": {
            "display_name": "Shuba",
            "account": null
          },
          "duration_seconds": 153.76,
          "web_url": "https://www.instagram.com/reels/audio/587784541076604/"
        },
        "content_summary": "A creator demonstrates a deshedding brush on a dog, describes a less-messy grooming routine, shows the result, and directs viewers to a discount in the Account bio.",
        "topics": [
          "dog_grooming",
          "at_home_pet_care"
        ],
        "creative_formats": [
          "talking_head",
          "product_demonstration",
          "creator_testimonial"
        ],
        "hook": {
          "construction": "The creator holds the brush beside a visibly shedding dog, states that it changed the grooming routine, and displays a seven-day result claim.",
          "devices": [
            "problem_callout",
            "direct_promise"
          ],
          "modalities": [
            "visual",
            "spoken",
            "on_screen_text"
          ]
        },
        "key_messages": [
          {
            "summary": "The brush is presented as making at-home shedding cleanup easier.",
            "roles": [
              "claim",
              "benefit",
              "use_case"
            ],
            "presentation": "asserted"
          }
        ],
        "proofs": [
          {
            "summary": "The creator demonstrates brushing the dog and shows the collected hair.",
            "mechanisms": [
              "live_product_demonstration",
              "result_reveal"
            ],
            "cited_source_types": []
          }
        ],
        "offers": [
          {
            "summary": "20% off with a stated promo code.",
            "types": [
              "discount",
              "promo_code"
            ],
            "stated_terms": [
              "20% off",
              "GROOM20"
            ]
          }
        ],
        "calls_to_action": [
          {
            "summary": "Use the link in the Account bio.",
            "actions": [
              "visit_profile_link"
            ],
            "stages": [
              "closing"
            ],
            "modalities": [
              "spoken",
              "on_screen_text",
              "caption"
            ]
          }
        ],
        "narrative_structure": {
          "description": "Problem framing, product demonstration, result reveal, then offer and CTA.",
          "patterns": [
            "problem_solution",
            "demonstration_to_result",
            "offer_close"
          ]
        },
        "has_paid_partnership_label": false,
        "paid_partners": [],
        "commercial_contexts": [
          "promo_code",
          "seller_behavior"
        ],
        "comments_enabled": true,
        "views": 412000,
        "likes": 28600,
        "comments": 354,
        "engagement_rate_by_views": 0.0703,
        "view_ratio_to_account_baseline": 6.2,
        "author": {
          "id": "ig_account_2j1x",
          "handle": "dogmomdaily",
          "display_name": "Dog Mom Daily",
          "web_url": "https://www.instagram.com/dogmomdaily/",
          "avatar_url": "https://media.tryklint.ai/accounts/ig_account_2j1x/avatar",
          "followers_count": 21400,
          "is_verified": false
        },
        "coauthors": []
      },
      {
        "id": "ig_post_9m3t",
        "shortcode": "DMq7RwXk2Pd",
        "web_url": "https://www.instagram.com/reel/DMq7RwXk2Pd/",
        "posted_at": "2026-06-24T19:15:00Z",
        "observed_at": "2026-07-14T13:40:00Z",
        "format": "reel",
        "primary_language": "en",
        "caption": "POV: shedding season with a husky 😅 This grooming glove is the only thing keeping our couch alive. #huskylife #sheddingseason #doggrooming",
        "hashtags": [
          "huskylife",
          "sheddingseason",
          "doggrooming"
        ],
        "caption_mentions": [],
        "audio": {
          "id": "ig_audio_2b8c",
          "instagram_id": null,
          "type": "original_sound",
          "title": "Original audio",
          "attribution": {
            "display_name": "brodyandbear",
            "account": {
              "id": "ig_account_3d6p",
              "handle": "brodyandbear",
              "display_name": "Brody & Bear",
              "web_url": "https://www.instagram.com/brodyandbear/",
              "avatar_url": "https://media.tryklint.ai/accounts/ig_account_3d6p/avatar",
              "followers_count": 12400,
              "is_verified": false
            }
          },
          "duration_seconds": 18.9,
          "web_url": null
        },
        "content_summary": "A dog owner films a casual at-home demonstration of a grooming glove on a shedding husky, showing the removed undercoat and joking about protecting the couch.",
        "topics": [
          "dog_grooming",
          "at_home_pet_care"
        ],
        "creative_formats": [
          "product_demonstration"
        ],
        "hook": {
          "construction": "A point-of-view framing of shedding season opens on a husky mid-shed before the owner pulls out the grooming glove.",
          "devices": [
            "relatable_scenario"
          ],
          "modalities": [
            "visual",
            "on_screen_text"
          ]
        },
        "key_messages": [
          {
            "summary": "The grooming glove is presented as an easy way to control husky shedding at home.",
            "roles": [
              "claim",
              "benefit"
            ],
            "presentation": "asserted"
          }
        ],
        "proofs": [
          {
            "summary": "The owner demonstrates the glove on the husky and shows the removed fur.",
            "mechanisms": [
              "live_product_demonstration",
              "result_reveal"
            ],
            "cited_source_types": []
          }
        ],
        "offers": [],
        "calls_to_action": [],
        "narrative_structure": null,
        "has_paid_partnership_label": false,
        "paid_partners": [],
        "commercial_contexts": [],
        "comments_enabled": true,
        "views": 156000,
        "likes": 9800,
        "comments": 412,
        "engagement_rate_by_views": 0.0655,
        "view_ratio_to_account_baseline": null,
        "author": {
          "id": "ig_account_3d6p",
          "handle": "brodyandbear",
          "display_name": "Brody & Bear",
          "web_url": "https://www.instagram.com/brodyandbear/",
          "avatar_url": "https://media.tryklint.ai/accounts/ig_account_3d6p/avatar",
          "followers_count": 12400,
          "is_verified": false
        },
        "coauthors": []
      }
    ],
    "has_more": true,
    "next_cursor": "cur_example_opaque_continuation_token"
  }
  ```
</Accordion>

Continuation sends **only** the cursor, plus an optional same-or-lower `limit`:

```json theme={null}
{
  "cursor": "cur_example_opaque_continuation_token",
  "limit": 2
}
```

<Accordion title="Final page response">
  ```json theme={null}
  {
    "request_id": "req_example_09",
    "data": [
      {
        "id": "ig_post_3p7d",
        "shortcode": "DMxR4kWq9Ln",
        "web_url": "https://www.instagram.com/reel/DMxR4kWq9Ln/",
        "posted_at": "2026-06-18T17:30:00Z",
        "observed_at": "2026-07-14T11:05:00Z",
        "format": "reel",
        "primary_language": "en",
        "caption": "The deshedding mistake I see every week in the salon 🙈 Try this instead (works with any slicker brush).\n\n#groomingtips #deshedding",
        "hashtags": [
          "groomingtips",
          "deshedding"
        ],
        "caption_mentions": [],
        "audio": null,
        "content_summary": "A professional groomer demonstrates a common deshedding mistake on a client dog, then shows a corrected slicker-brush technique and the reduced coat damage.",
        "topics": [
          "dog_grooming"
        ],
        "creative_formats": [
          "talking_head",
          "product_demonstration"
        ],
        "hook": {
          "construction": "The groomer names a mistake she sees weekly in the salon while showing the matted result on a client dog.",
          "devices": [
            "problem_callout"
          ],
          "modalities": [
            "visual",
            "spoken"
          ]
        },
        "key_messages": [
          {
            "summary": "Brushing direction and pressure matter more than the specific brush.",
            "roles": [
              "claim",
              "use_case"
            ],
            "presentation": "asserted"
          }
        ],
        "proofs": [
          {
            "summary": "The groomer demonstrates both techniques on the same dog and compares the results.",
            "mechanisms": [
              "live_product_demonstration"
            ],
            "cited_source_types": []
          }
        ],
        "offers": [],
        "calls_to_action": [
          {
            "summary": "Follow for weekly grooming technique tips.",
            "actions": [
              "follow_account"
            ],
            "stages": [
              "closing"
            ],
            "modalities": [
              "spoken"
            ]
          }
        ],
        "narrative_structure": null,
        "has_paid_partnership_label": false,
        "paid_partners": [],
        "commercial_contexts": [],
        "comments_enabled": true,
        "views": 89400,
        "likes": 5210,
        "comments": 154,
        "engagement_rate_by_views": 0.06,
        "view_ratio_to_account_baseline": null,
        "author": {
          "id": "ig_account_9t4w",
          "handle": "groomwithgrace",
          "display_name": "Grace | Groom With Grace",
          "web_url": "https://www.instagram.com/groomwithgrace/",
          "avatar_url": "https://media.tryklint.ai/accounts/ig_account_9t4w/avatar",
          "followers_count": 18900,
          "is_verified": false
        },
        "coauthors": []
      }
    ],
    "has_more": false,
    "next_cursor": null
  }
  ```
</Accordion>

The rules:

* **The sequence never recomputes.** Later pages traverse the pinned set; a post published after your search never appears mid-pagination. Run a new search to see newer state.
* **`has_more` speaks about the pinned session.** `has_more: false` exhausts the discovered window; it is not proof that Instagram holds no other matches.
* **Pages can run short.** Klint suppresses a post deleted after the snapshot and doesn't refill the page.
* **Cursors expire.** After a short lifetime, continuation returns `410 expired-cursor` rather than silently recomputing against live data:

```json theme={null}
{
  "type": "https://api.tryklint.ai/problems/expired-cursor",
  "status": 410,
  "request_id": "req_example_52",
  "detail": "This cursor's pinned search session has ended. Start a new search to see current results."
}
```

## Reading the results

Every result, from query search, filters-only, or pagination, is the identical complete post summary. A few semantics make the fields trustworthy:

* **A carousel is one post.** `media[]` holds ordered items in Instagram's publication order; Klint never splits a carousel into several posts. Transcript, on-screen text, and duration live on the media item that produced them, never flattened onto the post.
* **`null`, `[]`, and omitted mean different things.** `null` = applicable but not currently supportable (not evaluated yet, source unavailable, or evaluation failed). `[]` = evaluated and affirmatively empty. An omitted field (video-only fields on an image item) = structurally inapplicable. Failure never degrades to `[]`.
* **Enrichment publishes in whole units.** Creative interpretation (`content_summary`, `topics`, `hook`, `key_messages`, `offers`, …) appears as one coherent generation; you never see half of it. There is no `status` or progress field. Re-fetch later; completed units have simply appeared.
* **Metrics are current observations.** `views`, `likes`, `comments` follow strict target-post semantics; incompatible source values surface as `null`, never as guesses. Delivery URLs are Klint-controlled routes, never upstream Instagram CDN URLs.

Follow any result's `id` to the full post with [Get post](/docs/api-reference/instagram/get-post); search and GET return the identical representation.

## Limits

Provisional bounds (implementation hypotheses; evals may tighten them before contract freeze):

| Limit                                                   |            Value |
| ------------------------------------------------------- | ---------------: |
| Values per `in` / `contains_any` / `contains_all` array |              100 |
| Filter fields per request                               |               20 |
| `query` length                                          | 2,000 characters |
| Default page / max page                                 |         20 / 100 |

Violations use `422 validation-failed` with reason `OUT_OF_RANGE`.

## Continue from here

<Columns cols={2}>
  <Card title="Search accounts" icon="users" href="/docs/instagram/search/accounts-search">
    Qualify whole accounts by who they currently are.
  </Card>

  <Card title="API reference" icon="code" href="/docs/api-reference/instagram/search-posts">
    The full request and response schema.
  </Card>
</Columns>
