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

# Get Profile Comments

> Fetch the comments a professional profile has written, each with the post it was written on

## Endpoint

```
GET /api/v1/profile/comments
```

This endpoint returns the comments a member has **made**, anywhere — each one
paired with the full context of the post it was made on (its text, its author,
its media and its engagement counts).

<Info>
  Do not confuse it with
  [Get Post Comments](/api-reference/endpoint/get-post-comments), which goes the
  other way round: that one takes a **post** and returns the comments left
  **on** it. This one takes a **profile** and returns the comments that profile
  **wrote**.
</Info>

## Authentication

Include your API key in the request header:

```bash theme={null}
X-API-Key: your-api-key-here
```

## Parameters

<ParamField query="profileUrlOrUrn" type="string" required>
  The professional profile whose comments to fetch. Accepts any of:

  * **Profile URN**, recommended for consistency: a profile's public identifier (slug) can change over time, the URN does not. Example: `urn:li:fsd_profile:ACoAAA8BYqEBCGLg_vT_ca6mMEqkpp9nVffJ3hc`
  * **Public identifier (slug)**, also fine. Example: `williamhgates`
  * **Profile URL**. Example: `https://www.linkedin.com/in/williamhgates` (a trailing slash makes no difference)

  The slug is the last path segment of a profile URL. Pass just the slug, not the `/in/` prefix.

  Member profiles only: a company page URL or URN is rejected with a `400` error, free of charge.
</ParamField>

<ParamField query="count" type="integer" default="10">
  Number of comments to fetch per page.

  * Minimum: 1 — `0` or a negative value is rejected with `400`
  * Maximum: 100 — a higher value is clamped, not rejected
  * Default: 10
</ParamField>

<ParamField query="start" type="integer" default="0" deprecated>
  **Not supported on this endpoint.** This feed is cursor-paginated and ignores
  offsets, so a non-zero `start` is rejected with `400` rather than silently
  returning the first page again. Use `paginationToken`.
</ParamField>

<ParamField query="paginationToken" type="string">
  Cursor for the next page. Pass back the `paginationToken` from the previous
  response, unchanged; omit it to start from the beginning. Keep paging while
  `hasMore` is `true`.

  Pass it back verbatim. A token this API did not issue is not rejected — it is
  forwarded, and the page comes back empty and still costs a credit, so do not
  construct or edit one.
</ParamField>

## Response

<ResponseField name="comments" type="array">
  Array of comments the profile wrote, newest first. Each item carries the
  comment itself, its author, and the post it was written on.

  <Expandable title="Comment object">
    <ResponseField name="commentText" type="string">
      The text of the comment.
    </ResponseField>

    <ResponseField name="commentUrn" type="string">
      Unique identifier of the comment.
    </ResponseField>

    <ResponseField name="commentLink" type="string">
      Permalink to the comment.
    </ResponseField>

    <ResponseField name="isPinned" type="boolean">
      Whether the post's author pinned this comment to the top of the thread.
    </ResponseField>

    <ResponseField name="createdAt" type="string">
      ISO 8601 timestamp of when the comment was written.
    </ResponseField>

    <ResponseField name="stats" type="object">
      Engagement on the comment itself.

      <Expandable title="Comment stats object">
        <ResponseField name="totalReactions" type="integer">
          Total reactions the comment received.
        </ResponseField>

        <ResponseField name="comments" type="integer">
          Number of replies to this comment.
        </ResponseField>

        <ResponseField name="reactions" type="object">
          Per-type breakdown of the comment's reactions.

          <Expandable title="Reactions object">
            <ResponseField name="like" type="integer">
              Like reactions.
            </ResponseField>

            <ResponseField name="appreciation" type="integer">
              Support reactions.
            </ResponseField>

            <ResponseField name="empathy" type="integer">
              Love reactions.
            </ResponseField>

            <ResponseField name="interest" type="integer">
              Insightful reactions.
            </ResponseField>

            <ResponseField name="praise" type="integer">
              Celebrate reactions.
            </ResponseField>
          </Expandable>
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="commenter" type="object">
      Who wrote the comment — the profile you asked for.

      <Expandable title="Commenter object">
        <ResponseField name="name" type="string">
          Full name of the commenter.
        </ResponseField>

        <ResponseField name="subtitle" type="string">
          The line shown under the commenter's name, usually their headline.
        </ResponseField>

        <ResponseField name="url" type="string">
          Professional profile URL of the commenter.
        </ResponseField>

        <ResponseField name="profilePictureUrl" type="string">
          Profile picture URL of the commenter.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="post" type="object">
      The post the comment was written on.

      <Expandable title="Post object">
        <ResponseField name="postText" type="string">
          Text of the post.
        </ResponseField>

        <ResponseField name="postUrl" type="string">
          Public permalink to the post.
        </ResponseField>

        <ResponseField name="postUrn" type="string">
          The bare numeric activity id of the post, without any URN prefix.
        </ResponseField>

        <ResponseField name="date" type="string">
          ISO 8601 timestamp of when the post was published.
        </ResponseField>

        <ResponseField name="author" type="object">
          Who published the post.

          <Expandable title="Author object">
            <ResponseField name="name" type="string">
              Full name of the post author.
            </ResponseField>

            <ResponseField name="headline" type="string">
              Professional headline of the post author.
            </ResponseField>

            <ResponseField name="url" type="string">
              Professional profile URL of the post author.
            </ResponseField>

            <ResponseField name="profilePictureUrl" type="string">
              Profile picture URL of the post author, or `null` when they have none.
            </ResponseField>
          </Expandable>
        </ResponseField>

        <ResponseField name="stats" type="object">
          Engagement on the post.

          <Expandable title="Post stats object">
            <ResponseField name="totalReactions" type="integer">
              Total reactions the post received.
            </ResponseField>

            <ResponseField name="comments" type="integer">
              Total comments on the post.
            </ResponseField>

            <ResponseField name="reposts" type="integer">
              Number of times the post was reshared.
            </ResponseField>

            <ResponseField name="reactions" type="object">
              Per-type breakdown of the post's reactions: `like`, `appreciation`,
              `empathy`, `interest` and `praise`, all integers.
            </ResponseField>
          </Expandable>
        </ResponseField>

        <ResponseField name="images" type="array">
          Images attached to the post, each with `url`, `width` and `height`.
          Always present; an empty array when the post carries no image — and also
          when it carries a video, because the two are mutually exclusive here.
        </ResponseField>

        <ResponseField name="video" type="object">
          Video attached to the post. Always present; `null` when the post has
          none. Carries `url`, `duration` and `thumbnail`, plus the raw upstream
          stream metadata (`progressiveStreams`, `aspectRatio`, `entityUrn`,
          `provider`, `media`) — treat those as additive and do not depend on them.
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="paginationToken" type="string">
  Token for fetching the next page of comments. Do not read its presence as
  "there is more": decide on `hasMore`.
</ResponseField>

<ResponseField name="hasMore" type="boolean">
  Indicates whether there are more comments to fetch.
</ResponseField>

## Example Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.fetchin.io/api/v1/profile/comments?profileUrlOrUrn=https://www.linkedin.com/in/williamhgates&count=5" \
    -H "X-API-Key: your-api-key-here"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    'https://api.fetchin.io/api/v1/profile/comments?profileUrlOrUrn=https://www.linkedin.com/in/williamhgates&count=5',
    {
      headers: {
        'X-API-Key': 'your-api-key-here'
      }
    }
  );

  const data = await response.json();
  console.log(data.comments);
  ```

  ```python Python theme={null}
  import requests

  headers = {
      'X-API-Key': 'your-api-key-here'
  }

  params = {
      'profileUrlOrUrn': 'https://www.linkedin.com/in/williamhgates',
      'count': 5
  }

  response = requests.get(
      'https://api.fetchin.io/api/v1/profile/comments',
      headers=headers,
      params=params
  )

  data = response.json()
  print(data['comments'])
  ```

  ```php PHP theme={null}
  <?php

  $apiKey = 'your-api-key-here';
  $profileUrl = 'https://www.linkedin.com/in/williamhgates';
  $count = 5;

  $url = "https://api.fetchin.io/api/v1/profile/comments?profileUrlOrUrn=" . urlencode($profileUrl) . "&count=" . $count;

  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'X-API-Key: ' . $apiKey
  ]);

  $response = curl_exec($ch);
  $data = json_decode($response, true);

  curl_close($ch);
  print_r($data['comments']);
  ?>
  ```
</CodeGroup>

## Example Response

<ResponseExample>
  ```json 200 Success theme={null}
  {
    "comments": [
      {
        "commentText": "Congratulations to the whole team — this is the kind of progress that compounds.",
        "commentUrn": "urn:li:comment:(urn:li:activity:7486820978292072449,7486901233445109760)",
        "commentLink": "https://www.linkedin.com/feed/update/urn:li:activity:7486820978292072449?commentUrn=urn%3Ali%3Acomment%3A%28urn%3Ali%3Aactivity%3A7486820978292072449%2C7486901233445109760%29",
        "isPinned": false,
        "createdAt": "2026-07-25T18:04:12.000Z",
        "stats": {
          "totalReactions": 184,
          "comments": 7,
          "reactions": {
            "like": 151,
            "appreciation": 12,
            "empathy": 11,
            "interest": 6,
            "praise": 4
          }
        },
        "commenter": {
          "name": "Bill Gates",
          "subtitle": "Chair, Gates Foundation and Founder, Breakthrough Energy",
          "url": "https://www.linkedin.com/in/williamhgates",
          "profilePictureUrl": "https://media.licdn.com/dms/image/..."
        },
        "post": {
          "postText": "We just published our annual report on primary health care financing. Three findings surprised us.",
          "postUrl": "https://www.linkedin.com/posts/gatesfoundation_annual-report-primary-health-care-activity-7486820978292072449-ab1c",
          "postUrn": "7486820978292072449",
          "date": "2026-07-25T16:33:39.632Z",
          "author": {
            "name": "Gates Foundation",
            "headline": "Every person deserves the chance to live a healthy, productive life.",
            "url": "https://www.linkedin.com/company/gatesfoundation",
            "profilePictureUrl": "https://media.licdn.com/dms/image/..."
          },
          "stats": {
            "totalReactions": 4490,
            "comments": 425,
            "reposts": 230,
            "reactions": {
              "like": 4139,
              "appreciation": 63,
              "empathy": 159,
              "interest": 23,
              "praise": 104
            }
          },
          "images": [
            {
              "url": "https://media.licdn.com/dms/image/...",
              "width": 2048,
              "height": 1365
            }
          ],
          "video": null
        }
      },
      {
        "commentText": "Agreed. The hard part is not the model, it is the data pipeline behind it.",
        "commentUrn": "urn:li:comment:(urn:li:activity:7409540219328344064,7409601884712173568)",
        "commentLink": "https://www.linkedin.com/feed/update/urn:li:activity:7409540219328344064?commentUrn=urn%3Ali%3Acomment%3A%28urn%3Ali%3Aactivity%3A7409540219328344064%2C7409601884712173568%29",
        "isPinned": true,
        "createdAt": "2026-01-20T15:48:03.000Z",
        "stats": {
          "totalReactions": 23,
          "comments": 1,
          "reactions": {
            "like": 20,
            "appreciation": 0,
            "empathy": 1,
            "interest": 2,
            "praise": 0
          }
        },
        "commenter": {
          "name": "Bill Gates",
          "subtitle": "Chair, Gates Foundation and Founder, Breakthrough Energy",
          "url": "https://www.linkedin.com/in/williamhgates",
          "profilePictureUrl": "https://media.licdn.com/dms/image/..."
        },
        "post": {
          "postText": "Six months of inference cost data, in one chart.",
          "postUrl": "https://www.linkedin.com/posts/milanmilanovic_inference-cost-activity-7409540219328344064-9xkd",
          "postUrn": "7409540219328344064",
          "date": "2026-01-20T14:20:00.000Z",
          "author": {
            "name": "Dr Milan Milanovic",
            "headline": "Helping 400K+ engineers and leaders grow",
            "url": "https://www.linkedin.com/in/milanmilanovic",
            "profilePictureUrl": null
          },
          "stats": {
            "totalReactions": 635,
            "comments": 59,
            "reposts": 18,
            "reactions": {
              "like": 571,
              "appreciation": 9,
              "empathy": 14,
              "interest": 33,
              "praise": 8
            }
          },
          "video": {
            "url": "https://dms.licdn.com/playlist/vid/...",
            "duration": 48120,
            "thumbnail": "https://media.licdn.com/dms/image/..."
          }
        }
      }
    ],
    "paginationToken": "dXJuOmxpOmNvbW1lbnQ6NzQwOTYwMTg4NDcxMjE3MzU2OC0xNzY1MDA1NTU3NTM4",
    "hasMore": true
  }
  ```

  ```json 400 Bad Request theme={null}
  {
    "error": "Missing profileUrlOrUrn parameter",
    "code": "MISSING_PARAMETER"
  }
  ```

  ```json 401 Unauthorized theme={null}
  {
    "error": "Invalid API key",
    "code": "INVALID_API_KEY"
  }
  ```

  ```json 404 Not Found theme={null}
  {
    "error": "Profile not found",
    "code": "PROFILE_NOT_FOUND"
  }
  ```

  ```json 402 Payment Required theme={null}
  {
    "error": "Quota exceeded. Upgrade your plan or wait for renewal.",
    "code": "QUOTA_EXHAUSTED",
    "details": {
      "creditsRemaining": 0,
      "subscriptionCreditsRemaining": 0,
      "paygCreditsRemaining": 0,
      "buyCreditsUrl": "https://fetchin.io/credits"
    }
  }
  ```

  ```json 500 Internal Server Error theme={null}
  {
    "error": "Internal server error",
    "code": "INTERNAL_ERROR"
  }
  ```

  ```json 503 Service Unavailable theme={null}
  {
    "error": "Service temporarily unable to serve this request. Please retry.",
    "code": "SERVICE_UNAVAILABLE"
  }
  ```
</ResponseExample>

## Errors

See [Error Handling](/concepts/error-handling) for the full list of error codes and recommended handling.

* `400` `MISSING_PARAMETER` / `INVALID_PARAMETER` / `INVALID_URN`
* `401` `INVALID_API_KEY`
* `404` `PROFILE_NOT_FOUND`
* `402` `QUOTA_EXHAUSTED`
* `429` `RATE_LIMITED`
* `500` `INTERNAL_ERROR`
* `503` `SERVICE_UNAVAILABLE`

## Pagination

To collect a profile's whole comment history:

1. Make an initial request without `paginationToken`
2. If `hasMore` is `true`, use the returned `paginationToken` in your next request
3. Continue until `hasMore` is `false` — not until a page comes back short

```javascript theme={null}
async function fetchAllProfileComments(profileUrl) {
  const allComments = [];
  let paginationToken = null;
  let hasMore = true;

  while (hasMore) {
    const params = new URLSearchParams({
      profileUrlOrUrn: profileUrl,
      count: '100'
    });
    if (paginationToken) {
      params.set('paginationToken', paginationToken);
    }

    const response = await fetch(
      `https://api.fetchin.io/api/v1/profile/comments?${params}`,
      { headers: { 'X-API-Key': 'your-api-key-here' } }
    );

    const data = await response.json();
    allComments.push(...data.comments);
    paginationToken = data.paginationToken;
    hasMore = data.hasMore;
  }

  return allComments;
}
```

## Notes

<Info>
  This endpoint consumes 1 credit from your credit balance per API call, regardless of the `count` parameter value. Errors are free — with one exception: a `404` not found costs 1 credit. See [Quotas](/concepts/quotas).
</Info>

<Warning>
  Comments are returned in reverse chronological order (most recent first), and
  `count` is a ceiling rather than a promise: a page requested with `count=100`
  routinely comes back with slightly fewer items. **A short page is not the end
  of the feed** — keep paging while `hasMore` is `true`, and never stop because
  you received fewer comments than you asked for.
</Warning>

<Tip>
  Each item already embeds the post it was written on — its text, author, media
  and engagement counts — so you rarely need a follow-up call to
  [Get Posts](/api-reference/endpoint/get-posts) to make a comment
  actionable.
</Tip>

## Use Cases

<CardGroup cols={2}>
  <Card title="Buying-intent signals" icon="bullseye">
    Spot prospects commenting on your category, your competitors or your own content
  </Card>

  <Card title="Voice of the customer" icon="comments">
    Mine what a decision maker actually writes, in their own words, for personalized outreach
  </Card>

  <Card title="Network mapping" icon="diagram-project">
    See whose posts a profile keeps engaging with to infer relationships and influence
  </Card>

  <Card title="Lead scoring" icon="star">
    Score leads on how often, how recently and how substantively they comment
  </Card>
</CardGroup>


## OpenAPI

````yaml GET /api/v1/profile/comments
openapi: 3.1.0
info:
  title: Fetchin API
  version: 1.0.0
  description: Public B2B data API for fetching posts and profile information
servers:
  - url: https://api.fetchin.io
    description: Production server
security:
  - ApiKeyAuth: []
paths:
  /api/v1/profile/comments:
    get:
      summary: Get comments a profile has written
      description: >-
        Fetch the comments a member has made, newest first, each paired with the
        full context of the post it was written on (text, author, media and
        engagement counts). This is the inverse of `GET /api/v1/post/comments`,
        which takes a post and returns the comments left on it. `count` is a
        ceiling, not a promise: a page can come back with fewer items while more
        remain, so page while `hasMore` is true rather than stopping on a short
        page.
      parameters:
        - name: profileUrlOrUrn
          in: query
          required: true
          description: >-
            The professional profile whose comments to fetch. Accepts a profile
            URN (recommended for consistency, since a profile's public
            identifier can change over time while the URN does not; example
            `urn:li:fsd_profile:ACoAAA8BYqEBCGLg_vT_ca6mMEqkpp9nVffJ3hc`), a
            public identifier/slug (also fine; example `williamhgates`), or a
            full profile URL (example
            `https://www.linkedin.com/in/williamhgates`; a trailing slash is
            ignored). The slug is the last path segment of a profile URL, so
            pass just the slug, not the `/in/` prefix. Member profiles only: a
            company page URL or URN is rejected with a `400` error, free of
            charge.
          schema:
            type: string
            example: urn:li:fsd_profile:ACoAAA8BYqEBCGLg_vT_ca6mMEqkpp9nVffJ3hc
        - name: count
          in: query
          required: false
          description: >-
            Number of comments to fetch per page (default: 10). Values above 100
            are clamped to 100. This is a ceiling: a page can return slightly
            fewer items without meaning the feed is exhausted.
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 10
        - name: start
          in: query
          required: false
          description: >-
            Not supported on this endpoint. This feed is cursor-paginated and
            ignores offsets, so a non-zero value is rejected with 400 rather
            than silently returning the first page again. Page with
            `paginationToken` instead.
          schema:
            type: integer
            minimum: 0
            default: 0
          deprecated: true
        - name: paginationToken
          in: query
          required: false
          description: >-
            Cursor for the next page: pass back the `paginationToken` from the
            previous response, unchanged. Omit it to start from the beginning.
            Pass it back verbatim: a token this API did not issue is NOT
            rejected here, it is forwarded, and the page comes back empty and
            still costs a credit. Keep paging while `hasMore` is true.
          schema:
            type: string
      responses:
        '200':
          description: Successfully fetched the comments the profile has written
          content:
            application/json:
              schema:
                type: object
                properties:
                  comments:
                    type: array
                    description: Comments the profile wrote, newest first.
                    items:
                      type: object
                      properties:
                        commentText:
                          type: string
                          description: Text of the comment.
                          example: Congratulations to the whole team.
                        commentUrn:
                          type: string
                          description: Unique identifier of the comment.
                          example: >-
                            urn:li:comment:(urn:li:activity:7486820978292072449,7486901233445109760)
                        commentLink:
                          type: string
                          description: Permalink to the comment.
                        isPinned:
                          type: boolean
                          description: >-
                            Whether the post's author pinned this comment to the
                            top of the thread.
                        createdAt:
                          type: string
                          format: date-time
                          description: When the comment was written.
                        stats:
                          type: object
                          description: Engagement on the comment itself.
                          properties:
                            totalReactions:
                              type: integer
                              description: Total reactions the comment received.
                            comments:
                              type: integer
                              description: Number of replies to this comment.
                            reactions:
                              type: object
                              description: Per-type breakdown of the comment's reactions.
                              properties:
                                like:
                                  type: integer
                                appreciation:
                                  type: integer
                                empathy:
                                  type: integer
                                interest:
                                  type: integer
                                praise:
                                  type: integer
                        commenter:
                          type: object
                          description: >-
                            Who wrote the comment - the profile that was
                            requested.
                          properties:
                            name:
                              type: string
                              example: Bill Gates
                            subtitle:
                              type: string
                              description: >-
                                The line shown under the commenter's name,
                                usually their headline.
                              example: >-
                                Chair, Gates Foundation and Founder,
                                Breakthrough Energy
                            url:
                              type: string
                              example: https://www.linkedin.com/in/williamhgates
                            profilePictureUrl:
                              type: string
                              example: https://media.licdn.com/dms/image/...
                        post:
                          type: object
                          description: The post the comment was written on.
                          properties:
                            postText:
                              type: string
                              description: Text of the post.
                            postUrl:
                              type: string
                              description: Public permalink to the post.
                            postUrn:
                              type: string
                              description: >-
                                The bare numeric activity id of the post,
                                without any URN prefix.
                              example: '7486820978292072449'
                            date:
                              type: string
                              format: date-time
                              description: When the post was published.
                            author:
                              type: object
                              description: Who published the post.
                              properties:
                                name:
                                  type: string
                                headline:
                                  type: string
                                url:
                                  type: string
                                profilePictureUrl:
                                  type: string
                                  nullable: true
                                  description: >-
                                    Profile picture URL of the post author, or
                                    null when they have none.
                            stats:
                              type: object
                              description: Engagement on the post.
                              properties:
                                totalReactions:
                                  type: integer
                                comments:
                                  type: integer
                                reposts:
                                  type: integer
                                  description: Number of times the post was reshared.
                                reactions:
                                  type: object
                                  description: Per-type breakdown of the post's reactions.
                                  properties:
                                    like:
                                      type: integer
                                    appreciation:
                                      type: integer
                                    empathy:
                                      type: integer
                                    interest:
                                      type: integer
                                    praise:
                                      type: integer
                            images:
                              type: array
                              description: >-
                                Images attached to the post. Absent on posts
                                without images.
                              items:
                                type: object
                                properties:
                                  url:
                                    type: string
                                  width:
                                    type: integer
                                  height:
                                    type: integer
                            video:
                              type: object
                              nullable: true
                              description: >-
                                Video attached to the post. Absent or null on
                                posts without a video.
                              properties:
                                url:
                                  type: string
                                duration:
                                  type: integer
                                  description: Duration in milliseconds.
                                thumbnail:
                                  type: string
                  paginationToken:
                    type: string
                    description: >-
                      Token for fetching the next page. Only present when more
                      comments are available.
                  hasMore:
                    type: boolean
                    description: Whether more comments are available.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
components:
  responses:
    BadRequest:
      description: Bad request - a required parameter is missing or a value is invalid.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            missingParameter:
              value:
                error: Missing profileUrlOrUrn parameter
                code: MISSING_PARAMETER
            invalidParameter:
              value:
                error: limit must be a number between 1 and 100
                code: INVALID_PARAMETER
            invalidUrn:
              value:
                error: 'Invalid URN format: urn:li:member:123456789'
                code: INVALID_URN
    Unauthorized:
      description: Unauthorized - the X-API-Key header is missing or invalid.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            missingApiKey:
              value:
                error: Missing API key. Include X-API-Key header.
                code: UNAUTHENTICATED
            invalidApiKey:
              value:
                error: Invalid API key
                code: INVALID_API_KEY
    PaymentRequired:
      description: >-
        Payment required - you are out of credits (QUOTA_EXHAUSTED): the plan
        allowance for the current period is spent AND no pay-as-you-go credits
        are left. Buy pay-as-you-go credits (self-serve,
        https://fetchin.io/credits), upgrade your plan, or wait for renewal;
        retrying will not help and no Retry-After is sent. Distinct from the
        per-second rate limit, which is a 429 (RATE_LIMITED).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            quotaExhausted:
              value:
                error: Quota exceeded. Upgrade your plan or wait for renewal.
                code: QUOTA_EXHAUSTED
                details:
                  creditsRemaining: 0
                  subscriptionCreditsRemaining: 0
                  paygCreditsRemaining: 0
                  buyCreditsUrl: https://fetchin.io/credits
    NotFound:
      description: >-
        Not found - the request was served successfully but the requested
        professional entity does not exist.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            profileNotFound:
              value:
                error: LinkedIn profile not found
                code: PROFILE_NOT_FOUND
            postNotFound:
              value:
                error: Unable to find post from url
                code: POST_NOT_FOUND
            companyNotFound:
              value:
                error: Unable to find company slug from urn
                code: COMPANY_NOT_FOUND
    TooManyRequests:
      description: >-
        Too many requests - your per-second rate limit (RATE_LIMITED) was
        exceeded. Back off and retry, honoring the Retry-After header. (Running
        out of credits is a separate 402 PaymentRequired / QUOTA_EXHAUSTED, and
        buying credits never raises this per-second limit.)
      headers:
        Retry-After:
          description: Number of seconds to wait before retrying the request.
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            rateLimited:
              value:
                error: Rate limit exceeded. Try again later.
                code: RATE_LIMITED
    InternalError:
      description: >-
        Internal server error - an unexpected error occurred in our API. Safe to
        retry; contact support if it persists.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            internalError:
              value:
                error: Internal server error
                code: INTERNAL_ERROR
    ServiceUnavailable:
      description: >-
        Service unavailable - our API is temporarily unable to serve this
        request (capacity exhausted or overloaded). This is on our side, not
        yours and not an upstream service outage. Retry with backoff, honoring
        the Retry-After header.
      headers:
        Retry-After:
          description: Number of seconds to wait before retrying the request.
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            serviceUnavailable:
              value:
                error: >-
                  Service temporarily unable to serve this request. Please
                  retry.
                code: SERVICE_UNAVAILABLE
  schemas:
    Error:
      type: object
      required:
        - error
        - code
      properties:
        error:
          type: string
          description: >-
            Human-readable description of what went wrong. For display/logging;
            do not branch on this string.
        code:
          type: string
          enum:
            - MISSING_PARAMETER
            - INVALID_PARAMETER
            - INVALID_URN
            - UNAUTHENTICATED
            - INVALID_API_KEY
            - FORBIDDEN
            - NOT_FOUND
            - PROFILE_NOT_FOUND
            - POST_NOT_FOUND
            - COMPANY_NOT_FOUND
            - ENDPOINT_REMOVED
            - RATE_LIMITED
            - QUOTA_EXHAUSTED
            - INTERNAL_ERROR
            - UPSTREAM_ERROR
            - SERVICE_UNAVAILABLE
            - UPSTREAM_TIMEOUT
          description: >-
            Stable, machine-readable error code. Branch your integration on this
            value, not on the HTTP status alone or the message text.
        details:
          type: object
          additionalProperties: true
          description: >-
            Optional structured context. On QUOTA_EXHAUSTED it carries the
            balance breakdown at the moment of the rejection - creditsRemaining,
            subscriptionCreditsRemaining, paygCreditsRemaining - plus
            buyCreditsUrl, the self-serve page for buying more credits. Always
            additive and never guaranteed: read it for diagnostics and logs, but
            branch on `code` and do not require any field of it.
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.